comparison src/share/vm/runtime/globals.cpp @ 11070:6e3634222155

8017611: Auto corrector for mistyped vm options Summary: The auto corrector for mistyped vm options fuzzy-matches existing flags based on string similarity (Dice's coefficient). Reviewed-by: kvn, dsamersoff, hseigel, johnc
author tamao
date Fri, 28 Jun 2013 20:18:04 -0700
parents b3cd8b58b798
children 6b0fd0964b87 f98f5d48f511
comparison
equal deleted inserted replaced
11069:5ea20b3bd249 11070:6e3634222155
274 }; 274 };
275 275
276 Flag* Flag::flags = flagTable; 276 Flag* Flag::flags = flagTable;
277 size_t Flag::numFlags = (sizeof(flagTable) / sizeof(Flag)); 277 size_t Flag::numFlags = (sizeof(flagTable) / sizeof(Flag));
278 278
279 inline bool str_equal(const char* s, char* q, size_t len) { 279 inline bool str_equal(const char* s, const char* q, size_t len) {
280 // s is null terminated, q is not! 280 // s is null terminated, q is not!
281 if (strlen(s) != (unsigned int) len) return false; 281 if (strlen(s) != (unsigned int) len) return false;
282 return strncmp(s, q, len) == 0; 282 return strncmp(s, q, len) == 0;
283 } 283 }
284 284
285 // Search the flag table for a named flag 285 // Search the flag table for a named flag
286 Flag* Flag::find_flag(char* name, size_t length, bool allow_locked) { 286 Flag* Flag::find_flag(const char* name, size_t length, bool allow_locked) {
287 for (Flag* current = &flagTable[0]; current->name != NULL; current++) { 287 for (Flag* current = &flagTable[0]; current->name != NULL; current++) {
288 if (str_equal(current->name, name, length)) { 288 if (str_equal(current->name, name, length)) {
289 // Found a matching entry. Report locked flags only if allowed. 289 // Found a matching entry. Report locked flags only if allowed.
290 if (!(current->is_unlocked() || current->is_unlocker())) { 290 if (!(current->is_unlocked() || current->is_unlocker())) {
291 if (!allow_locked) { 291 if (!allow_locked) {
299 } 299 }
300 // Flag name is not in the flag table 300 // Flag name is not in the flag table
301 return NULL; 301 return NULL;
302 } 302 }
303 303
304 // Compute string similarity based on Dice's coefficient
305 static float str_similar(const char* str1, const char* str2, size_t len2) {
306 int len1 = (int) strlen(str1);
307 int total = len1 + (int) len2;
308
309 int hit = 0;
310
311 for (int i = 0; i < len1 -1; ++i) {
312 for (int j = 0; j < (int) len2 -1; ++j) {
313 if ((str1[i] == str2[j]) && (str1[i+1] == str2[j+1])) {
314 ++hit;
315 break;
316 }
317 }
318 }
319
320 return 2.0f * (float) hit / (float) total;
321 }
322
323 Flag* Flag::fuzzy_match(const char* name, size_t length, bool allow_locked) {
324 float VMOptionsFuzzyMatchSimilarity = 0.7f;
325 Flag* match = NULL;
326 float score;
327 float max_score = -1;
328
329 for (Flag* current = &flagTable[0]; current->name != NULL; current++) {
330 score = str_similar(current->name, name, length);
331 if (score > max_score) {
332 max_score = score;
333 match = current;
334 }
335 }
336
337 if (!(match->is_unlocked() || match->is_unlocker())) {
338 if (!allow_locked) {
339 return NULL;
340 }
341 }
342
343 if (max_score < VMOptionsFuzzyMatchSimilarity) {
344 return NULL;
345 }
346
347 return match;
348 }
349
304 // Returns the address of the index'th element 350 // Returns the address of the index'th element
305 static Flag* address_of_flag(CommandLineFlagWithType flag) { 351 static Flag* address_of_flag(CommandLineFlagWithType flag) {
306 assert((size_t)flag < Flag::numFlags, "bad command line flag index"); 352 assert((size_t)flag < Flag::numFlags, "bad command line flag index");
307 return &Flag::flags[flag]; 353 return &Flag::flags[flag];
308 } 354 }