Mercurial > hg > graal-jvmci-8
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(), ""); |