diff 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
line wrap: on
line diff
--- a/src/share/vm/runtime/globals.cpp	Mon Jul 01 09:30:23 2013 -0700
+++ b/src/share/vm/runtime/globals.cpp	Fri Jun 28 20:18:04 2013 -0700
@@ -276,14 +276,14 @@
 Flag* Flag::flags = flagTable;
 size_t Flag::numFlags = (sizeof(flagTable) / sizeof(Flag));
 
-inline bool str_equal(const char* s, char* q, size_t len) {
+inline bool str_equal(const char* s, const char* q, size_t len) {
   // s is null terminated, q is not!
   if (strlen(s) != (unsigned int) len) return false;
   return strncmp(s, q, len) == 0;
 }
 
 // Search the flag table for a named flag
-Flag* Flag::find_flag(char* name, size_t length, bool allow_locked) {
+Flag* Flag::find_flag(const char* name, size_t length, bool allow_locked) {
   for (Flag* current = &flagTable[0]; current->name != NULL; current++) {
     if (str_equal(current->name, name, length)) {
       // Found a matching entry.  Report locked flags only if allowed.
@@ -301,6 +301,52 @@
   return NULL;
 }
 
+// Compute string similarity based on Dice's coefficient
+static float str_similar(const char* str1, const char* str2, size_t len2) {
+  int len1 = (int) strlen(str1);
+  int total = len1 + (int) len2;
+
+  int hit = 0;
+
+  for (int i = 0; i < len1 -1; ++i) {
+    for (int j = 0; j < (int) len2 -1; ++j) {
+      if ((str1[i] == str2[j]) && (str1[i+1] == str2[j+1])) {
+        ++hit;
+        break;
+      }
+    }
+  }
+
+  return 2.0f * (float) hit / (float) total;
+}
+
+Flag* Flag::fuzzy_match(const char* name, size_t length, bool allow_locked) {
+  float VMOptionsFuzzyMatchSimilarity = 0.7f;
+  Flag* match = NULL;
+  float score;
+  float max_score = -1;
+
+  for (Flag* current = &flagTable[0]; current->name != NULL; current++) {
+    score = str_similar(current->name, name, length);
+    if (score > max_score) {
+      max_score = score;
+      match = current;
+    }
+  }
+
+  if (!(match->is_unlocked() || match->is_unlocker())) {
+    if (!allow_locked) {
+      return NULL;
+    }
+  }
+
+  if (max_score < VMOptionsFuzzyMatchSimilarity) {
+    return NULL;
+  }
+
+  return match;
+}
+
 // Returns the address of the index'th element
 static Flag* address_of_flag(CommandLineFlagWithType flag) {
   assert((size_t)flag < Flag::numFlags, "bad command line flag index");