comparison src/share/vm/oops/methodOop.cpp @ 3779:04760e41b01e

7016112: CMS: crash during promotion testing Summary: Also reviewed by mikael.gerdin@oracle.com; stdlib:qsort() does byte-by-byte swapping on Windows. This leads to pointer shearing. Fix is to implement a quicksort that does full pointer updates. Reviewed-by: never, coleenp, ysr
author brutisso
date Tue, 28 Jun 2011 14:23:27 +0200
parents 328926869b15
children 4bf3cbef0b3e
comparison
equal deleted inserted replaced
3778:5f6f2615433a 3779:04760e41b01e
47 #include "runtime/frame.inline.hpp" 47 #include "runtime/frame.inline.hpp"
48 #include "runtime/handles.inline.hpp" 48 #include "runtime/handles.inline.hpp"
49 #include "runtime/relocator.hpp" 49 #include "runtime/relocator.hpp"
50 #include "runtime/sharedRuntime.hpp" 50 #include "runtime/sharedRuntime.hpp"
51 #include "runtime/signature.hpp" 51 #include "runtime/signature.hpp"
52 #include "utilities/quickSort.hpp"
52 #include "utilities/xmlstream.hpp" 53 #include "utilities/xmlstream.hpp"
53 54
54 55
55 // Implementation of methodOopDesc 56 // Implementation of methodOopDesc
56 57
1202 #endif 1203 #endif
1203 name()->print_symbol_on(st); 1204 name()->print_symbol_on(st);
1204 if (WizardMode) signature()->print_symbol_on(st); 1205 if (WizardMode) signature()->print_symbol_on(st);
1205 } 1206 }
1206 1207
1207
1208 extern "C" {
1209 static int method_compare(methodOop* a, methodOop* b) {
1210 return (*a)->name()->fast_compare((*b)->name());
1211 }
1212
1213 // Prevent qsort from reordering a previous valid sort by
1214 // considering the address of the methodOops if two methods
1215 // would otherwise compare as equal. Required to preserve
1216 // optimal access order in the shared archive. Slower than
1217 // method_compare, only used for shared archive creation.
1218 static int method_compare_idempotent(methodOop* a, methodOop* b) {
1219 int i = method_compare(a, b);
1220 if (i != 0) return i;
1221 return ( a < b ? -1 : (a == b ? 0 : 1));
1222 }
1223
1224 // We implement special compare versions for narrow oops to avoid
1225 // testing for UseCompressedOops on every comparison.
1226 static int method_compare_narrow(narrowOop* a, narrowOop* b) {
1227 methodOop m = (methodOop)oopDesc::load_decode_heap_oop(a);
1228 methodOop n = (methodOop)oopDesc::load_decode_heap_oop(b);
1229 return m->name()->fast_compare(n->name());
1230 }
1231
1232 static int method_compare_narrow_idempotent(narrowOop* a, narrowOop* b) {
1233 int i = method_compare_narrow(a, b);
1234 if (i != 0) return i;
1235 return ( a < b ? -1 : (a == b ? 0 : 1));
1236 }
1237
1238 typedef int (*compareFn)(const void*, const void*);
1239 }
1240
1241
1242 // This is only done during class loading, so it is OK to assume method_idnum matches the methods() array 1208 // This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
1243 static void reorder_based_on_method_index(objArrayOop methods, 1209 static void reorder_based_on_method_index(objArrayOop methods,
1244 objArrayOop annotations, 1210 objArrayOop annotations,
1245 GrowableArray<oop>* temp_array) { 1211 GrowableArray<oop>* temp_array) {
1246 if (annotations == NULL) { 1212 if (annotations == NULL) {
1260 methodOop m = (methodOop) methods->obj_at(i); 1226 methodOop m = (methodOop) methods->obj_at(i);
1261 annotations->obj_at_put(i, temp_array->at(m->method_idnum())); 1227 annotations->obj_at_put(i, temp_array->at(m->method_idnum()));
1262 } 1228 }
1263 } 1229 }
1264 1230
1231 // Comparer for sorting an object array containing
1232 // methodOops.
1233 template <class T>
1234 static int method_comparator(T a, T b) {
1235 methodOop m = (methodOop)oopDesc::decode_heap_oop_not_null(a);
1236 methodOop n = (methodOop)oopDesc::decode_heap_oop_not_null(b);
1237 return m->name()->fast_compare(n->name());
1238 }
1265 1239
1266 // This is only done during class loading, so it is OK to assume method_idnum matches the methods() array 1240 // This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
1267 void methodOopDesc::sort_methods(objArrayOop methods, 1241 void methodOopDesc::sort_methods(objArrayOop methods,
1268 objArrayOop methods_annotations, 1242 objArrayOop methods_annotations,
1269 objArrayOop methods_parameter_annotations, 1243 objArrayOop methods_parameter_annotations,
1282 for (int i = 0; i < length; i++) { 1256 for (int i = 0; i < length; i++) {
1283 methodOop m = (methodOop) methods->obj_at(i); 1257 methodOop m = (methodOop) methods->obj_at(i);
1284 m->set_method_idnum(i); 1258 m->set_method_idnum(i);
1285 } 1259 }
1286 } 1260 }
1287 1261 {
1288 // Use a simple bubble sort for small number of methods since 1262 No_Safepoint_Verifier nsv;
1289 // qsort requires a functional pointer call for each comparison. 1263 if (UseCompressedOops) {
1290 if (length < 8) { 1264 QuickSort::sort<narrowOop>((narrowOop*)(methods->base()), length, method_comparator<narrowOop>, idempotent);
1291 bool sorted = true; 1265 } else {
1292 for (int i=length-1; i>0; i--) { 1266 QuickSort::sort<oop>((oop*)(methods->base()), length, method_comparator<oop>, idempotent);
1293 for (int j=0; j<i; j++) {
1294 methodOop m1 = (methodOop)methods->obj_at(j);
1295 methodOop m2 = (methodOop)methods->obj_at(j+1);
1296 if ((uintptr_t)m1->name() > (uintptr_t)m2->name()) {
1297 methods->obj_at_put(j, m2);
1298 methods->obj_at_put(j+1, m1);
1299 sorted = false;
1300 }
1301 }
1302 if (sorted) break;
1303 sorted = true;
1304 } 1267 }
1305 } else { 1268 if (UseConcMarkSweepGC) {
1306 compareFn compare = 1269 // For CMS we need to dirty the cards for the array
1307 (UseCompressedOops ? 1270 BarrierSet* bs = Universe::heap()->barrier_set();
1308 (compareFn) (idempotent ? method_compare_narrow_idempotent : method_compare_narrow): 1271 assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt");
1309 (compareFn) (idempotent ? method_compare_idempotent : method_compare)); 1272 bs->write_ref_array(methods->base(), length);
1310 qsort(methods->base(), length, heapOopSize, compare); 1273 }
1311 } 1274 }
1312 1275
1313 // Sort annotations if necessary 1276 // Sort annotations if necessary
1314 assert(methods_annotations == NULL || methods_annotations->length() == methods->length(), ""); 1277 assert(methods_annotations == NULL || methods_annotations->length() == methods->length(), "");
1315 assert(methods_parameter_annotations == NULL || methods_parameter_annotations->length() == methods->length(), ""); 1278 assert(methods_parameter_annotations == NULL || methods_parameter_annotations->length() == methods->length(), "");