src/share/vm/ci/ciReplay.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Sdiff src/share/vm/ci

src/share/vm/ci/ciReplay.cpp

Print this page
rev 6132 : 8026694: New type profiling points break compilation replay
Summary: fixes compilation replay with new profiling points
Reviewed-by:


  31 #include "memory/allocation.inline.hpp"
  32 #include "memory/oopFactory.hpp"
  33 #include "memory/resourceArea.hpp"
  34 #include "utilities/copy.hpp"
  35 #include "utilities/macros.hpp"
  36 
  37 #ifndef PRODUCT
  38 
  39 // ciReplay
  40 
  41 typedef struct _ciMethodDataRecord {
  42   const char* _klass_name;
  43   const char* _method_name;
  44   const char* _signature;
  45 
  46   int _state;
  47   int _current_mileage;
  48 
  49   intptr_t* _data;
  50   char*     _orig_data;
  51   jobject*  _oops_handles;
  52   int*      _oops_offsets;


  53   int       _data_length;
  54   int       _orig_data_length;
  55   int       _oops_length;

  56 } ciMethodDataRecord;
  57 
  58 typedef struct _ciMethodRecord {
  59   const char* _klass_name;
  60   const char* _method_name;
  61   const char* _signature;
  62 
  63   int _instructions_size;
  64   int _interpreter_invocation_count;
  65   int _interpreter_throwout_count;
  66   int _invocation_counter;
  67   int _backedge_counter;
  68 } ciMethodRecord;
  69 
  70 typedef struct _ciInlineRecord {
  71   const char* _klass_name;
  72   const char* _method_name;
  73   const char* _signature;
  74 
  75   int _inline_depth;


 544     CompileBroker::compile_method(method, entry_bci, comp_level,
 545                                   methodHandle(), 0, "replay", THREAD);
 546     replay_state = NULL;
 547     reset();
 548   }
 549 
 550   // ciMethod <klass> <name> <signature> <invocation_counter> <backedge_counter> <interpreter_invocation_count> <interpreter_throwout_count> <instructions_size>
 551   //
 552   //
 553   void process_ciMethod(TRAPS) {
 554     Method* method = parse_method(CHECK);
 555     if (had_error()) return;
 556     ciMethodRecord* rec = new_ciMethod(method);
 557     rec->_invocation_counter = parse_int("invocation_counter");
 558     rec->_backedge_counter = parse_int("backedge_counter");
 559     rec->_interpreter_invocation_count = parse_int("interpreter_invocation_count");
 560     rec->_interpreter_throwout_count = parse_int("interpreter_throwout_count");
 561     rec->_instructions_size = parse_int("instructions_size");
 562   }
 563 
 564   // ciMethodData <klass> <name> <signature> <state> <current mileage> orig <length> # # ... data <length> # # ... oops <length>
 565   void process_ciMethodData(TRAPS) {
 566     Method* method = parse_method(CHECK);
 567     if (had_error()) return;
 568     /* jsut copied from Method, to build interpret data*/
 569     if (InstanceRefKlass::owns_pending_list_lock((JavaThread*)THREAD)) {
 570       return;
 571     }




 572     // methodOopDesc::build_interpreter_method_data(method, CHECK);
 573     {
 574       // Grab a lock here to prevent multiple
 575       // MethodData*s from being created.
 576       MutexLocker ml(MethodData_lock, THREAD);
 577       if (method->method_data() == NULL) {
 578         ClassLoaderData* loader_data = method->method_holder()->class_loader_data();
 579         MethodData* method_data = MethodData::allocate(loader_data, method, CHECK);
 580         method->set_method_data(method_data);
 581       }
 582     }
 583 
 584     // collect and record all the needed information for later
 585     ciMethodDataRecord* rec = new_ciMethodData(method);
 586     rec->_state = parse_int("state");
 587     rec->_current_mileage = parse_int("current_mileage");
 588 
 589     rec->_orig_data = parse_data("orig", rec->_orig_data_length);
 590     if (rec->_orig_data == NULL) {
 591       return;
 592     }
 593     rec->_data = parse_intptr_data("data", rec->_data_length);
 594     if (rec->_data == NULL) {
 595       return;
 596     }
 597     if (!parse_tag_and_count("oops", rec->_oops_length)) {
 598       return;
 599     }
 600     rec->_oops_handles = NEW_RESOURCE_ARRAY(jobject, rec->_oops_length);
 601     rec->_oops_offsets = NEW_RESOURCE_ARRAY(int, rec->_oops_length);
 602     for (int i = 0; i < rec->_oops_length; i++) {
 603       int offset = parse_int("offset");
 604       if (had_error()) {
 605         return;
 606       }
 607       Klass* k = parse_klass(CHECK);
 608       rec->_oops_offsets[i] = offset;
 609       KlassHandle *kh = NEW_C_HEAP_OBJ(KlassHandle, mtCompiler);
 610       ::new ((void*)kh) KlassHandle(THREAD, k);
 611       rec->_oops_handles[i] = (jobject)kh;













 612     }
 613   }
 614 
 615   // instanceKlass <name>
 616   //
 617   // Loads and initializes the klass 'name'.  This can be used to
 618   // create particular class loading environments
 619   void process_instanceKlass(TRAPS) {
 620     // just load the referenced class
 621     Klass* k = parse_klass(CHECK);
 622   }
 623 
 624   // ciInstanceKlass <name> <is_linked> <is_initialized> <length> tag # # # ...
 625   //
 626   // Load the klass 'name' and link or initialize it.  Verify that the
 627   // constant pool is the same length as 'length' and make sure the
 628   // constant pool tags are in the same state.
 629   void process_ciInstanceKlass(TRAPS) {
 630     InstanceKlass* k = (InstanceKlass *)parse_klass(CHECK);
 631     int is_linked = parse_int("is_linked");


1080   if (replay_state == NULL) {
1081     return;
1082   }
1083 
1084   ASSERT_IN_VM;
1085   ResourceMark rm;
1086 
1087   Method* method = m->get_MethodData()->method();
1088   ciMethodDataRecord* rec = replay_state->find_ciMethodDataRecord(method);
1089   if (rec == NULL) {
1090     // This indicates some mismatch with the original environment and
1091     // the replay environment though it's not always enough to
1092     // interfere with reproducing a bug
1093     tty->print_cr("Warning: requesting ciMethodData record for method with no data: ");
1094     method->print_name(tty);
1095     tty->cr();
1096   } else {
1097     m->_state = rec->_state;
1098     m->_current_mileage = rec->_current_mileage;
1099     if (rec->_data_length != 0) {
1100       assert(m->_data_size == rec->_data_length * (int)sizeof(rec->_data[0]), "must agree");
1101 
1102       // Write the correct ciObjects back into the profile data
1103       ciEnv* env = ciEnv::current();
1104       for (int i = 0; i < rec->_oops_length; i++) {
1105         KlassHandle *h = (KlassHandle *)rec->_oops_handles[i];
1106         *(ciMetadata**)(rec->_data + rec->_oops_offsets[i]) =
1107           env->get_metadata((*h)());







1108       }
1109       // Copy the updated profile data into place as intptr_ts
1110 #ifdef _LP64
1111       Copy::conjoint_jlongs_atomic((jlong *)rec->_data, (jlong *)m->_data, rec->_data_length);
1112 #else
1113       Copy::conjoint_jints_atomic((jint *)rec->_data, (jint *)m->_data, rec->_data_length);
1114 #endif
1115     }
1116 
1117     // copy in the original header
1118     Copy::conjoint_jbytes(rec->_orig_data, (char*)&m->_orig, rec->_orig_data_length);
1119   }
1120 }
1121 
1122 
1123 bool ciReplay::should_not_inline(ciMethod* method) {
1124   if (replay_state == NULL) {
1125     return false;
1126   }
1127   VM_ENTRY_MARK;




  31 #include "memory/allocation.inline.hpp"
  32 #include "memory/oopFactory.hpp"
  33 #include "memory/resourceArea.hpp"
  34 #include "utilities/copy.hpp"
  35 #include "utilities/macros.hpp"
  36 
  37 #ifndef PRODUCT
  38 
  39 // ciReplay
  40 
  41 typedef struct _ciMethodDataRecord {
  42   const char* _klass_name;
  43   const char* _method_name;
  44   const char* _signature;
  45 
  46   int _state;
  47   int _current_mileage;
  48 
  49   intptr_t* _data;
  50   char*     _orig_data;
  51   Klass**   _classes_handles;
  52   Method**  _methods_handles;
  53   int*      _classes_offsets;
  54   int*      _methods_offsets;
  55   int       _data_length;
  56   int       _orig_data_length;
  57   int       _classes_length;
  58   int       _methods_length;
  59 } ciMethodDataRecord;
  60 
  61 typedef struct _ciMethodRecord {
  62   const char* _klass_name;
  63   const char* _method_name;
  64   const char* _signature;
  65 
  66   int _instructions_size;
  67   int _interpreter_invocation_count;
  68   int _interpreter_throwout_count;
  69   int _invocation_counter;
  70   int _backedge_counter;
  71 } ciMethodRecord;
  72 
  73 typedef struct _ciInlineRecord {
  74   const char* _klass_name;
  75   const char* _method_name;
  76   const char* _signature;
  77 
  78   int _inline_depth;


 547     CompileBroker::compile_method(method, entry_bci, comp_level,
 548                                   methodHandle(), 0, "replay", THREAD);
 549     replay_state = NULL;
 550     reset();
 551   }
 552 
 553   // ciMethod <klass> <name> <signature> <invocation_counter> <backedge_counter> <interpreter_invocation_count> <interpreter_throwout_count> <instructions_size>
 554   //
 555   //
 556   void process_ciMethod(TRAPS) {
 557     Method* method = parse_method(CHECK);
 558     if (had_error()) return;
 559     ciMethodRecord* rec = new_ciMethod(method);
 560     rec->_invocation_counter = parse_int("invocation_counter");
 561     rec->_backedge_counter = parse_int("backedge_counter");
 562     rec->_interpreter_invocation_count = parse_int("interpreter_invocation_count");
 563     rec->_interpreter_throwout_count = parse_int("interpreter_throwout_count");
 564     rec->_instructions_size = parse_int("instructions_size");
 565   }
 566 
 567   // ciMethodData <klass> <name> <signature> <state> <current mileage> orig <length> # # ... data <length> # # ... oops <length> # ... methods <length>
 568   void process_ciMethodData(TRAPS) {
 569     Method* method = parse_method(CHECK);
 570     if (had_error()) return;
 571     /* just copied from Method, to build interpret data*/
 572     if (InstanceRefKlass::owns_pending_list_lock((JavaThread*)THREAD)) {
 573       return;
 574     }
 575     // To be properly initialized, some profiling in the MDO needs the
 576     // method to be rewritten (number of arguments at a call for
 577     // instance)
 578     method->method_holder()->link_class(CHECK);
 579     // methodOopDesc::build_interpreter_method_data(method, CHECK);
 580     {
 581       // Grab a lock here to prevent multiple
 582       // MethodData*s from being created.
 583       MutexLocker ml(MethodData_lock, THREAD);
 584       if (method->method_data() == NULL) {
 585         ClassLoaderData* loader_data = method->method_holder()->class_loader_data();
 586         MethodData* method_data = MethodData::allocate(loader_data, method, CHECK);
 587         method->set_method_data(method_data);
 588       }
 589     }
 590 
 591     // collect and record all the needed information for later
 592     ciMethodDataRecord* rec = new_ciMethodData(method);
 593     rec->_state = parse_int("state");
 594     rec->_current_mileage = parse_int("current_mileage");
 595 
 596     rec->_orig_data = parse_data("orig", rec->_orig_data_length);
 597     if (rec->_orig_data == NULL) {
 598       return;
 599     }
 600     rec->_data = parse_intptr_data("data", rec->_data_length);
 601     if (rec->_data == NULL) {
 602       return;
 603     }
 604     if (!parse_tag_and_count("oops", rec->_classes_length)) {
 605       return;
 606     }
 607     rec->_classes_handles = NEW_RESOURCE_ARRAY(Klass*, rec->_classes_length);
 608     rec->_classes_offsets = NEW_RESOURCE_ARRAY(int, rec->_classes_length);
 609     for (int i = 0; i < rec->_classes_length; i++) {
 610       int offset = parse_int("offset");
 611       if (had_error()) {
 612         return;
 613       }
 614       Klass* k = parse_klass(CHECK);
 615       rec->_classes_offsets[i] = offset;
 616       rec->_classes_handles[i] = k;
 617     }
 618 
 619     if (!parse_tag_and_count("methods", rec->_methods_length)) {
 620       return;
 621     }
 622     rec->_methods_handles = NEW_RESOURCE_ARRAY(Method*, rec->_methods_length);
 623     rec->_methods_offsets = NEW_RESOURCE_ARRAY(int, rec->_methods_length);
 624     for (int i = 0; i < rec->_methods_length; i++) {
 625       int offset = parse_int("offset");
 626       if (had_error()) {
 627         return;
 628       }
 629       Method* m = parse_method(CHECK);
 630       rec->_methods_offsets[i] = offset;
 631       rec->_methods_handles[i] = m;
 632     }
 633   }
 634 
 635   // instanceKlass <name>
 636   //
 637   // Loads and initializes the klass 'name'.  This can be used to
 638   // create particular class loading environments
 639   void process_instanceKlass(TRAPS) {
 640     // just load the referenced class
 641     Klass* k = parse_klass(CHECK);
 642   }
 643 
 644   // ciInstanceKlass <name> <is_linked> <is_initialized> <length> tag # # # ...
 645   //
 646   // Load the klass 'name' and link or initialize it.  Verify that the
 647   // constant pool is the same length as 'length' and make sure the
 648   // constant pool tags are in the same state.
 649   void process_ciInstanceKlass(TRAPS) {
 650     InstanceKlass* k = (InstanceKlass *)parse_klass(CHECK);
 651     int is_linked = parse_int("is_linked");


1100   if (replay_state == NULL) {
1101     return;
1102   }
1103 
1104   ASSERT_IN_VM;
1105   ResourceMark rm;
1106 
1107   Method* method = m->get_MethodData()->method();
1108   ciMethodDataRecord* rec = replay_state->find_ciMethodDataRecord(method);
1109   if (rec == NULL) {
1110     // This indicates some mismatch with the original environment and
1111     // the replay environment though it's not always enough to
1112     // interfere with reproducing a bug
1113     tty->print_cr("Warning: requesting ciMethodData record for method with no data: ");
1114     method->print_name(tty);
1115     tty->cr();
1116   } else {
1117     m->_state = rec->_state;
1118     m->_current_mileage = rec->_current_mileage;
1119     if (rec->_data_length != 0) {
1120       assert(m->_data_size + m->_extra_data_size == rec->_data_length * (int)sizeof(rec->_data[0]), "must agree");
1121 
1122       // Write the correct ciObjects back into the profile data
1123       ciEnv* env = ciEnv::current();
1124       for (int i = 0; i < rec->_classes_length; i++) {
1125         Klass *k = rec->_classes_handles[i];
1126         // In case this class pointer is is tagged, preserve the tag
1127         // bits
1128         rec->_data[rec->_classes_offsets[i]] =
1129           ciTypeEntries::with_status(env->get_metadata(k)->as_klass(), rec->_data[rec->_classes_offsets[i]]);
1130       }
1131       for (int i = 0; i < rec->_methods_length; i++) {
1132         Method *m = rec->_methods_handles[i];
1133         *(ciMetadata**)(rec->_data + rec->_methods_offsets[i]) =
1134           env->get_metadata(m);
1135       }
1136       // Copy the updated profile data into place as intptr_ts
1137 #ifdef _LP64
1138       Copy::conjoint_jlongs_atomic((jlong *)rec->_data, (jlong *)m->_data, rec->_data_length);
1139 #else
1140       Copy::conjoint_jints_atomic((jint *)rec->_data, (jint *)m->_data, rec->_data_length);
1141 #endif
1142     }
1143 
1144     // copy in the original header
1145     Copy::conjoint_jbytes(rec->_orig_data, (char*)&m->_orig, rec->_orig_data_length);
1146   }
1147 }
1148 
1149 
1150 bool ciReplay::should_not_inline(ciMethod* method) {
1151   if (replay_state == NULL) {
1152     return false;
1153   }
1154   VM_ENTRY_MARK;


src/share/vm/ci/ciReplay.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File