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) { 1125 if (annotations == NULL) { 1126 return; 1127 } 1128 1129 int length = methods->length(); 1130 int i; 1131 // Copy to temp array 1132 temp_array->clear(); 1133 for (i = 0; i < length; i++) { 1134 temp_array->append(annotations->obj_at(i)); 1135 } 1136 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); 1208 m->set_method_idnum(i); | 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 // We implement special compare versions for narrow oops to avoid 1118 // testing for UseCompressedOops on every comparison. 1119 static int method_compare_narrow(narrowOop* a, narrowOop* b) { 1120 methodOop m = (methodOop)oopDesc::load_decode_heap_oop(a); 1121 methodOop n = (methodOop)oopDesc::load_decode_heap_oop(b); 1122 return m->name()->fast_compare(n->name()); 1123 } 1124 1125 static int method_compare_narrow_idempotent(narrowOop* a, narrowOop* b) { 1126 int i = method_compare_narrow(a, b); 1127 if (i != 0) return i; 1128 return ( a < b ? -1 : (a == b ? 0 : 1)); 1129 } 1130 1131 typedef int (*compareFn)(const void*, const void*); 1132 } 1133 1134 1135 // This is only done during class loading, so it is OK to assume method_idnum matches the methods() array 1136 static void reorder_based_on_method_index(objArrayOop methods, 1137 objArrayOop annotations, 1138 GrowableArray<oop>* temp_array) { 1139 if (annotations == NULL) { 1140 return; 1141 } 1142 1143 int length = methods->length(); 1144 int i; 1145 // Copy to temp array 1146 temp_array->clear(); 1147 for (i = 0; i < length; i++) { 1148 temp_array->append(annotations->obj_at(i)); 1149 } 1150 1163 objArrayOop methods_default_annotations, 1164 bool idempotent) { 1165 int length = methods->length(); 1166 if (length > 1) { 1167 bool do_annotations = false; 1168 if (methods_annotations != NULL || 1169 methods_parameter_annotations != NULL || 1170 methods_default_annotations != NULL) { 1171 do_annotations = true; 1172 } 1173 if (do_annotations) { 1174 // Remember current method ordering so we can reorder annotations 1175 for (int i = 0; i < length; i++) { 1176 methodOop m = (methodOop) methods->obj_at(i); 1177 m->set_method_idnum(i); 1178 } 1179 } 1180 1181 // Use a simple bubble sort for small number of methods since 1182 // qsort requires a functional pointer call for each comparison. 1183 if (length < 8) { 1184 bool sorted = true; 1185 for (int i=length-1; i>0; i--) { 1186 for (int j=0; j<i; j++) { 1187 methodOop m1 = (methodOop)methods->obj_at(j); 1188 methodOop m2 = (methodOop)methods->obj_at(j+1); 1189 if ((uintptr_t)m1->name() > (uintptr_t)m2->name()) { 1190 methods->obj_at_put(j, m2); 1191 methods->obj_at_put(j+1, m1); 1192 sorted = false; 1193 } 1194 } 1195 if (sorted) break; 1196 sorted = true; 1197 } 1198 } else { 1199 compareFn compare = 1200 (UseCompressedOops ? 1201 (compareFn) (idempotent ? method_compare_narrow_idempotent : method_compare_narrow): 1202 (compareFn) (idempotent ? method_compare_idempotent : method_compare)); 1203 qsort(methods->base(), length, heapOopSize, compare); 1204 } 1205 1206 // Sort annotations if necessary 1207 assert(methods_annotations == NULL || methods_annotations->length() == methods->length(), ""); 1208 assert(methods_parameter_annotations == NULL || methods_parameter_annotations->length() == methods->length(), ""); 1209 assert(methods_default_annotations == NULL || methods_default_annotations->length() == methods->length(), ""); 1210 if (do_annotations) { 1211 ResourceMark rm; 1212 // Allocate temporary storage 1213 GrowableArray<oop>* temp_array = new GrowableArray<oop>(length); 1214 reorder_based_on_method_index(methods, methods_annotations, temp_array); 1215 reorder_based_on_method_index(methods, methods_parameter_annotations, temp_array); 1216 reorder_based_on_method_index(methods, methods_default_annotations, temp_array); 1217 } 1218 1219 // Reset method ordering 1220 for (int i = 0; i < length; i++) { 1221 methodOop m = (methodOop) methods->obj_at(i); 1222 m->set_method_idnum(i); |