1083 }
1084 }
1085 return false;
1086 }
1087
1088 // Exposed so field engineers can debug VM
1089 void methodOopDesc::print_short_name(outputStream* st) {
1090 ResourceMark rm;
1091 #ifdef PRODUCT
1092 st->print(" %s::", method_holder()->klass_part()->external_name());
1093 #else
1094 st->print(" %s::", method_holder()->klass_part()->internal_name());
1095 #endif
1096 name()->print_symbol_on(st);
1097 if (WizardMode) signature()->print_symbol_on(st);
1098 }
1099
1100
1101 extern "C" {
1102 static int method_compare(methodOop* a, methodOop* b) {
1103 return (*a)->name()->fast_compare((*b)->name());
1104 }
1105
1106 // Prevent qsort from reordering a previous valid sort by
1107 // considering the address of the methodOops if two methods
1108 // would otherwise compare as equal. Required to preserve
1109 // optimal access order in the shared archive. Slower than
1110 // method_compare, only used for shared archive creation.
1111 static int method_compare_idempotent(methodOop* a, methodOop* b) {
1112 int i = method_compare(a, b);
1113 if (i != 0) return i;
1114 return ( a < b ? -1 : (a == b ? 0 : 1));
1115 }
1116
1117 typedef int (*compareFn)(const void*, const void*);
1118 }
1119
1120
1121 // This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
1122 static void reorder_based_on_method_index(objArrayOop methods,
1123 objArrayOop annotations,
1124 GrowableArray<oop>* temp_array) {
1149 objArrayOop methods_default_annotations,
1150 bool idempotent) {
1151 int length = methods->length();
1152 if (length > 1) {
1153 bool do_annotations = false;
1154 if (methods_annotations != NULL ||
1155 methods_parameter_annotations != NULL ||
1156 methods_default_annotations != NULL) {
1157 do_annotations = true;
1158 }
1159 if (do_annotations) {
1160 // Remember current method ordering so we can reorder annotations
1161 for (int i = 0; i < length; i++) {
1162 methodOop m = (methodOop) methods->obj_at(i);
1163 m->set_method_idnum(i);
1164 }
1165 }
1166
1167 // Use a simple bubble sort for small number of methods since
1168 // qsort requires a functional pointer call for each comparison.
1169 if (UseCompressedOops || length < 8) {
1170 bool sorted = true;
1171 for (int i=length-1; i>0; i--) {
1172 for (int j=0; j<i; j++) {
1173 methodOop m1 = (methodOop)methods->obj_at(j);
1174 methodOop m2 = (methodOop)methods->obj_at(j+1);
1175 if ((uintptr_t)m1->name() > (uintptr_t)m2->name()) {
1176 methods->obj_at_put(j, m2);
1177 methods->obj_at_put(j+1, m1);
1178 sorted = false;
1179 }
1180 }
1181 if (sorted) break;
1182 sorted = true;
1183 }
1184 } else {
1185 // XXX This doesn't work for UseCompressedOops because the compare fn
1186 // will have to decode the methodOop anyway making it not much faster
1187 // than above.
1188 compareFn compare = (compareFn) (idempotent ? method_compare_idempotent : method_compare);
1189 qsort(methods->base(), length, heapOopSize, compare);
1190 }
1191
1192 // Sort annotations if necessary
1193 assert(methods_annotations == NULL || methods_annotations->length() == methods->length(), "");
1194 assert(methods_parameter_annotations == NULL || methods_parameter_annotations->length() == methods->length(), "");
1195 assert(methods_default_annotations == NULL || methods_default_annotations->length() == methods->length(), "");
1196 if (do_annotations) {
1197 ResourceMark rm;
1198 // Allocate temporary storage
1199 GrowableArray<oop>* temp_array = new GrowableArray<oop>(length);
1200 reorder_based_on_method_index(methods, methods_annotations, temp_array);
1201 reorder_based_on_method_index(methods, methods_parameter_annotations, temp_array);
1202 reorder_based_on_method_index(methods, methods_default_annotations, temp_array);
1203 }
1204
1205 // Reset method ordering
1206 for (int i = 0; i < length; i++) {
1207 methodOop m = (methodOop) methods->obj_at(i);
|
1083 }
1084 }
1085 return false;
1086 }
1087
1088 // Exposed so field engineers can debug VM
1089 void methodOopDesc::print_short_name(outputStream* st) {
1090 ResourceMark rm;
1091 #ifdef PRODUCT
1092 st->print(" %s::", method_holder()->klass_part()->external_name());
1093 #else
1094 st->print(" %s::", method_holder()->klass_part()->internal_name());
1095 #endif
1096 name()->print_symbol_on(st);
1097 if (WizardMode) signature()->print_symbol_on(st);
1098 }
1099
1100
1101 extern "C" {
1102 static int method_compare(methodOop* a, methodOop* b) {
1103 if (UseCompressedOops) {
1104 methodOop m = (methodOop)oopDesc::load_decode_heap_oop((narrowOop*)a);
1105 methodOop n = (methodOop)oopDesc::load_decode_heap_oop((narrowOop*)b);
1106 return m->name()->fast_compare(n->name());
1107 }
1108 else {
1109 return (*a)->name()->fast_compare((*b)->name());
1110 }
1111 }
1112
1113 // Prevent qsort from reordering a previous valid sort by
1114 // considering the address of the methodOops if two methods
1115 // would otherwise compare as equal. Required to preserve
1116 // optimal access order in the shared archive. Slower than
1117 // method_compare, only used for shared archive creation.
1118 static int method_compare_idempotent(methodOop* a, methodOop* b) {
1119 int i = method_compare(a, b);
1120 if (i != 0) return i;
1121 return ( a < b ? -1 : (a == b ? 0 : 1));
1122 }
1123
1124 typedef int (*compareFn)(const void*, const void*);
1125 }
1126
1127
1128 // This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
1129 static void reorder_based_on_method_index(objArrayOop methods,
1130 objArrayOop annotations,
1131 GrowableArray<oop>* temp_array) {
1156 objArrayOop methods_default_annotations,
1157 bool idempotent) {
1158 int length = methods->length();
1159 if (length > 1) {
1160 bool do_annotations = false;
1161 if (methods_annotations != NULL ||
1162 methods_parameter_annotations != NULL ||
1163 methods_default_annotations != NULL) {
1164 do_annotations = true;
1165 }
1166 if (do_annotations) {
1167 // Remember current method ordering so we can reorder annotations
1168 for (int i = 0; i < length; i++) {
1169 methodOop m = (methodOop) methods->obj_at(i);
1170 m->set_method_idnum(i);
1171 }
1172 }
1173
1174 // Use a simple bubble sort for small number of methods since
1175 // qsort requires a functional pointer call for each comparison.
1176 if (length < 8) {
1177 bool sorted = true;
1178 for (int i=length-1; i>0; i--) {
1179 for (int j=0; j<i; j++) {
1180 methodOop m1 = (methodOop)methods->obj_at(j);
1181 methodOop m2 = (methodOop)methods->obj_at(j+1);
1182 if ((uintptr_t)m1->name() > (uintptr_t)m2->name()) {
1183 methods->obj_at_put(j, m2);
1184 methods->obj_at_put(j+1, m1);
1185 sorted = false;
1186 }
1187 }
1188 if (sorted) break;
1189 sorted = true;
1190 }
1191 } else {
1192 compareFn compare = (compareFn) (idempotent ? method_compare_idempotent : method_compare);
1193 qsort(methods->base(), length, heapOopSize, compare);
1194 }
1195
1196 // Sort annotations if necessary
1197 assert(methods_annotations == NULL || methods_annotations->length() == methods->length(), "");
1198 assert(methods_parameter_annotations == NULL || methods_parameter_annotations->length() == methods->length(), "");
1199 assert(methods_default_annotations == NULL || methods_default_annotations->length() == methods->length(), "");
1200 if (do_annotations) {
1201 ResourceMark rm;
1202 // Allocate temporary storage
1203 GrowableArray<oop>* temp_array = new GrowableArray<oop>(length);
1204 reorder_based_on_method_index(methods, methods_annotations, temp_array);
1205 reorder_based_on_method_index(methods, methods_parameter_annotations, temp_array);
1206 reorder_based_on_method_index(methods, methods_default_annotations, temp_array);
1207 }
1208
1209 // Reset method ordering
1210 for (int i = 0; i < length; i++) {
1211 methodOop m = (methodOop) methods->obj_at(i);
|