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;
|