src/share/vm/oops/methodOop.cpp

Print this page
rev 2520 : 7016112: CMS: crash during promotion testing
Summary: 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:


1187       if (name == NULL) return true;
1188       klassOop klass = SystemDictionary::find(name, class_loader, protection_domain, THREAD);
1189       if (klass == NULL) return true;
1190     }
1191   }
1192   return false;
1193 }
1194 
1195 // Exposed so field engineers can debug VM
1196 void methodOopDesc::print_short_name(outputStream* st) {
1197   ResourceMark rm;
1198 #ifdef PRODUCT
1199   st->print(" %s::", method_holder()->klass_part()->external_name());
1200 #else
1201   st->print(" %s::", method_holder()->klass_part()->internal_name());
1202 #endif
1203   name()->print_symbol_on(st);
1204   if (WizardMode) signature()->print_symbol_on(st);
1205 }
1206 
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
1243 static void reorder_based_on_method_index(objArrayOop methods,
1244                                           objArrayOop annotations,
1245                                           GrowableArray<oop>* temp_array) {
1246   if (annotations == NULL) {
1247     return;
1248   }
1249 
1250   int length = methods->length();
1251   int i;
1252   // Copy to temp array
1253   temp_array->clear();
1254   for (i = 0; i < length; i++) {
1255     temp_array->append(annotations->obj_at(i));
1256   }
1257 
1258   // Copy back using old method indices
1259   for (i = 0; i < length; i++) {
1260     methodOop m = (methodOop) methods->obj_at(i);
1261     annotations->obj_at_put(i, temp_array->at(m->method_idnum()));
1262   }
1263 }
1264 








1265 
1266 // 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,
1268                                  objArrayOop methods_annotations,
1269                                  objArrayOop methods_parameter_annotations,
1270                                  objArrayOop methods_default_annotations,
1271                                  bool idempotent) {
1272   int length = methods->length();
1273   if (length > 1) {
1274     bool do_annotations = false;
1275     if (methods_annotations != NULL ||
1276         methods_parameter_annotations != NULL ||
1277         methods_default_annotations != NULL) {
1278       do_annotations = true;
1279     }
1280     if (do_annotations) {
1281       // Remember current method ordering so we can reorder annotations
1282       for (int i = 0; i < length; i++) {
1283         methodOop m = (methodOop) methods->obj_at(i);
1284         m->set_method_idnum(i);


1286     }
1287 
1288     // Use a simple bubble sort for small number of methods since
1289     // qsort requires a functional pointer call for each comparison.
1290     if (length < 8) {
1291       bool sorted = true;
1292       for (int i=length-1; i>0; i--) {
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       }
1305     } else {
1306       compareFn compare =
1307         (UseCompressedOops ?
1308          (compareFn) (idempotent ? method_compare_narrow_idempotent : method_compare_narrow):
1309          (compareFn) (idempotent ? method_compare_idempotent : method_compare));
1310       qsort(methods->base(), length, heapOopSize, compare);
1311     }
1312 
1313     // Sort annotations if necessary
1314     assert(methods_annotations == NULL           || methods_annotations->length() == methods->length(), "");
1315     assert(methods_parameter_annotations == NULL || methods_parameter_annotations->length() == methods->length(), "");
1316     assert(methods_default_annotations == NULL   || methods_default_annotations->length() == methods->length(), "");
1317     if (do_annotations) {
1318       ResourceMark rm;
1319       // Allocate temporary storage
1320       GrowableArray<oop>* temp_array = new GrowableArray<oop>(length);
1321       reorder_based_on_method_index(methods, methods_annotations, temp_array);
1322       reorder_based_on_method_index(methods, methods_parameter_annotations, temp_array);
1323       reorder_based_on_method_index(methods, methods_default_annotations, temp_array);
1324     }
1325 
1326     // Reset method ordering
1327     for (int i = 0; i < length; i++) {
1328       methodOop m = (methodOop) methods->obj_at(i);
1329       m->set_method_idnum(i);
1330     }




1187       if (name == NULL) return true;
1188       klassOop klass = SystemDictionary::find(name, class_loader, protection_domain, THREAD);
1189       if (klass == NULL) return true;
1190     }
1191   }
1192   return false;
1193 }
1194 
1195 // Exposed so field engineers can debug VM
1196 void methodOopDesc::print_short_name(outputStream* st) {
1197   ResourceMark rm;
1198 #ifdef PRODUCT
1199   st->print(" %s::", method_holder()->klass_part()->external_name());
1200 #else
1201   st->print(" %s::", method_holder()->klass_part()->internal_name());
1202 #endif
1203   name()->print_symbol_on(st);
1204   if (WizardMode) signature()->print_symbol_on(st);
1205 }
1206 



































1207 // This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
1208 static void reorder_based_on_method_index(objArrayOop methods,
1209                                           objArrayOop annotations,
1210                                           GrowableArray<oop>* temp_array) {
1211   if (annotations == NULL) {
1212     return;
1213   }
1214 
1215   int length = methods->length();
1216   int i;
1217   // Copy to temp array
1218   temp_array->clear();
1219   for (i = 0; i < length; i++) {
1220     temp_array->append(annotations->obj_at(i));
1221   }
1222 
1223   // Copy back using old method indices
1224   for (i = 0; i < length; i++) {
1225     methodOop m = (methodOop) methods->obj_at(i);
1226     annotations->obj_at_put(i, temp_array->at(m->method_idnum()));
1227   }
1228 }
1229 
1230 // Comparer for sorting an object array containing
1231 // methodOops.
1232 template <class T>
1233 static int method_comparer(T a, T b) {
1234   methodOop m = (methodOop)oopDesc::decode_heap_oop_not_null(a);
1235   methodOop n = (methodOop)oopDesc::decode_heap_oop_not_null(b);
1236   return m->name()->fast_compare(n->name());
1237 }
1238 
1239 // This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
1240 void methodOopDesc::sort_methods(objArrayOop methods,
1241                                  objArrayOop methods_annotations,
1242                                  objArrayOop methods_parameter_annotations,
1243                                  objArrayOop methods_default_annotations,
1244                                  bool idempotent) {
1245   int length = methods->length();
1246   if (length > 1) {
1247     bool do_annotations = false;
1248     if (methods_annotations != NULL ||
1249         methods_parameter_annotations != NULL ||
1250         methods_default_annotations != NULL) {
1251       do_annotations = true;
1252     }
1253     if (do_annotations) {
1254       // Remember current method ordering so we can reorder annotations
1255       for (int i = 0; i < length; i++) {
1256         methodOop m = (methodOop) methods->obj_at(i);
1257         m->set_method_idnum(i);


1259     }
1260 
1261     // Use a simple bubble sort for small number of methods since
1262     // qsort requires a functional pointer call for each comparison.
1263     if (length < 8) {
1264       bool sorted = true;
1265       for (int i=length-1; i>0; i--) {
1266         for (int j=0; j<i; j++) {
1267           methodOop m1 = (methodOop)methods->obj_at(j);
1268           methodOop m2 = (methodOop)methods->obj_at(j+1);
1269           if ((uintptr_t)m1->name() > (uintptr_t)m2->name()) {
1270             methods->obj_at_put(j, m2);
1271             methods->obj_at_put(j+1, m1);
1272             sorted = false;
1273           }
1274         }
1275         if (sorted) break;
1276           sorted = true;
1277       }
1278     } else {
1279       if (UseCompressedOops) {
1280         methods->sort<narrowOop>(method_comparer<narrowOop>, idempotent);
1281       } else {
1282         methods->sort<oop>(method_comparer<oop>, idempotent);
1283       }
1284     }
1285 
1286     // Sort annotations if necessary
1287     assert(methods_annotations == NULL           || methods_annotations->length() == methods->length(), "");
1288     assert(methods_parameter_annotations == NULL || methods_parameter_annotations->length() == methods->length(), "");
1289     assert(methods_default_annotations == NULL   || methods_default_annotations->length() == methods->length(), "");
1290     if (do_annotations) {
1291       ResourceMark rm;
1292       // Allocate temporary storage
1293       GrowableArray<oop>* temp_array = new GrowableArray<oop>(length);
1294       reorder_based_on_method_index(methods, methods_annotations, temp_array);
1295       reorder_based_on_method_index(methods, methods_parameter_annotations, temp_array);
1296       reorder_based_on_method_index(methods, methods_default_annotations, temp_array);
1297     }
1298 
1299     // Reset method ordering
1300     for (int i = 0; i < length; i++) {
1301       methodOop m = (methodOop) methods->obj_at(i);
1302       m->set_method_idnum(i);
1303     }