hotspot/src/share/vm/runtime/java.hpp
changeset 950 6112b627bb36
parent 781 e1baa9c8f16f
child 5547 f4b087cbb361
--- a/hotspot/src/share/vm/runtime/java.hpp	Sat Jul 19 17:38:22 2008 -0400
+++ b/hotspot/src/share/vm/runtime/java.hpp	Mon Jul 28 14:07:44 2008 -0400
@@ -48,100 +48,163 @@
 extern void vm_exit_during_initialization(const char* error, const char* message = NULL);
 extern void vm_shutdown_during_initialization(const char* error, const char* message = NULL);
 
-class JDK_Version : AllStatic {
+/**
+ * Discovering the JDK_Version during initialization is tricky when the
+ * running JDK is less than JDK6.  For JDK6 and greater, a "GetVersion"
+ * function exists in libjava.so and we simply call it during the
+ * 'initialize()' call to find the version.  For JDKs with version < 6, no
+ * such call exists and we have to probe the JDK in order to determine
+ * the exact version.  This probing cannot happen during late in
+ * the VM initialization process so there's a period of time during
+ * initialization when we don't know anything about the JDK version other than
+ * that it less than version 6.  This is the "partially initialized" time,
+ * when we can answer only certain version queries (such as, is the JDK
+ * version greater than 5?  Answer: no).  Once the JDK probing occurs, we
+ * know the version and are considered fully initialized.
+ */
+class JDK_Version VALUE_OBJ_CLASS_SPEC {
   friend class VMStructs;
+  friend class Universe;
+  friend void JDK_Version_init();
  private:
-  static jdk_version_info _version_info;
-  static bool             _pre_jdk16_version;
-  static int              _jdk_version;  // JDK version number representing the release
-                                         //  i.e. n in 1.n.x (= jdk_minor_version())
+
+  static JDK_Version _current;
+
+  // In this class, we promote the minor version of release to be the
+  // major version for releases >= 5 in anticipation of the JDK doing the
+  // same thing.  For example, we represent "1.5.0" as major version 5 (we
+  // drop the leading 1 and use 5 as the 'major').
+
+  uint8_t _major;
+  uint8_t _minor;
+  uint8_t _micro;
+  uint8_t _update;
+  uint8_t _special;
+  uint8_t _build;
+
+  // If partially initialized, the above fields are invalid and we know
+  // that we're less than major version 6.
+  bool _partially_initialized;
+
+  bool _thread_park_blocker;
+
+  bool is_valid() const {
+    return (_major != 0 || _partially_initialized);
+  }
+
+  // initializes or partially initializes the _current static field
+  static void initialize();
+
+  // Completes initialization for a pre-JDK6 version.
+  static void fully_initialize(uint8_t major, uint8_t minor = 0,
+                               uint8_t micro = 0, uint8_t update = 0);
 
  public:
-  static void initialize();
-  static int  jdk_major_version() { return JDK_VERSION_MAJOR(_version_info.jdk_version); }
-  static int  jdk_minor_version() { return JDK_VERSION_MINOR(_version_info.jdk_version); }
-  static int  jdk_micro_version() { return JDK_VERSION_MICRO(_version_info.jdk_version); }
-  static int  jdk_build_number()  { return JDK_VERSION_BUILD(_version_info.jdk_version); }
+
+  // Returns true if the the current version has only been partially initialized
+  static bool is_partially_initialized() {
+    return _current._partially_initialized;
+  }
+
+  JDK_Version() : _major(0), _minor(0), _micro(0), _update(0),
+                  _special(0), _build(0), _partially_initialized(false),
+                  _thread_park_blocker(false) {}
 
-  static bool is_pre_jdk16_version()        { return _pre_jdk16_version; }
-  static bool is_jdk12x_version()           { assert(is_jdk_version_initialized(), "must have been initialized"); return _jdk_version == 2; }
-  static bool is_jdk13x_version()           { assert(is_jdk_version_initialized(), "must have been initialized"); return _jdk_version == 3; }
-  static bool is_jdk14x_version()           { assert(is_jdk_version_initialized(), "must have been initialized"); return _jdk_version == 4; }
-  static bool is_jdk15x_version()           { assert(is_jdk_version_initialized(), "must have been initialized"); return _jdk_version == 5; }
+  JDK_Version(uint8_t major, uint8_t minor = 0, uint8_t micro = 0,
+              uint8_t update = 0, uint8_t special = 0, uint8_t build = 0,
+              bool thread_park_blocker = false) :
+      _major(major), _minor(minor), _micro(micro), _update(update),
+      _special(special), _build(build), _partially_initialized(false),
+      _thread_park_blocker(thread_park_blocker) {}
 
-  static bool is_jdk16x_version() {
-    if (is_jdk_version_initialized()) {
-      return _jdk_version == 6;
-    } else {
-      assert(is_pre_jdk16_version(), "must have been initialized");
-      return false;
-    }
+  // Returns the current running JDK version
+  static JDK_Version current() { return _current; }
+
+  // Factory methods for convenience
+  static JDK_Version jdk(uint8_t m) {
+    return JDK_Version(m);
+  }
+
+  static JDK_Version jdk_update(uint8_t major, uint8_t update_number) {
+    return JDK_Version(major, 0, 0, update_number);
   }
 
-  static bool is_jdk17x_version() {
-    if (is_jdk_version_initialized()) {
-      return _jdk_version == 7;
+  uint8_t major_version() const          { return _major; }
+  uint8_t minor_version() const          { return _minor; }
+  uint8_t micro_version() const          { return _micro; }
+  uint8_t update_version() const         { return _update; }
+  uint8_t special_update_version() const { return _special; }
+  uint8_t build_number() const           { return _build; }
+
+  bool supports_thread_park_blocker() const {
+    return _thread_park_blocker;
+  }
+
+  // Performs a full ordering comparison using all fields (update, build, etc.)
+  int compare(const JDK_Version& other) const;
+
+  /**
+   * Performs comparison using only the major version, returning negative
+   * if the major version of 'this' is less than the parameter, 0 if it is
+   * equal, and a positive value if it is greater.
+   */
+  int compare_major(int version) const {
+    if (_partially_initialized) {
+      if (version >= 6) {
+        return -1;
+      } else {
+        assert(false, "Can't make this comparison during init time");
+        return -1; // conservative
+      }
     } else {
-      assert(is_pre_jdk16_version(), "must have been initialized");
-      return false;
+      return major_version() - version;
     }
   }
 
-  static bool supports_thread_park_blocker() { return _version_info.thread_park_blocker; }
+  void to_string(char* buffer, size_t buflen) const;
+
+  // Convenience methods for queries on the current major/minor version
+  static bool is_jdk12x_version() {
+    return current().compare_major(2) == 0;
+  }
+
+  static bool is_jdk13x_version() {
+    return current().compare_major(3) == 0;
+  }
+
+  static bool is_jdk14x_version() {
+    return current().compare_major(4) == 0;
+  }
+
+  static bool is_jdk15x_version() {
+    return current().compare_major(5) == 0;
+  }
+
+  static bool is_jdk16x_version() {
+    return current().compare_major(6) == 0;
+  }
+
+  static bool is_jdk17x_version() {
+    return current().compare_major(7) == 0;
+  }
+
+  static bool is_gte_jdk13x_version() {
+    return current().compare_major(3) >= 0;
+  }
 
   static bool is_gte_jdk14x_version() {
-    // Keep the semantics of this that the version number is >= 1.4
-    assert(is_jdk_version_initialized(), "Not initialized");
-    return _jdk_version >= 4;
-  }
-  static bool is_gte_jdk15x_version() {
-    // Keep the semantics of this that the version number is >= 1.5
-    assert(is_jdk_version_initialized(), "Not initialized");
-    return _jdk_version >= 5;
+    return current().compare_major(4) >= 0;
   }
+
+  static bool is_gte_jdk15x_version() {
+    return current().compare_major(5) >= 0;
+  }
+
   static bool is_gte_jdk16x_version() {
-    // Keep the semantics of this that the version number is >= 1.6
-    if (is_jdk_version_initialized()) {
-      return _jdk_version >= 6;
-    } else {
-      assert(is_pre_jdk16_version(), "Not initialized");
-      return false;
-    }
+    return current().compare_major(6) >= 0;
   }
 
   static bool is_gte_jdk17x_version() {
-    // Keep the semantics of this that the version number is >= 1.7
-    if (is_jdk_version_initialized()) {
-      return _jdk_version >= 7;
-    } else {
-      assert(is_pre_jdk16_version(), "Not initialized");
-      return false;
-    }
-  }
-
-  static bool is_jdk_version_initialized() {
-    return _jdk_version > 0;
-  }
-
-  // These methods are defined to deal with pre JDK 1.6 versions
-  static void set_jdk12x_version() {
-    assert(_pre_jdk16_version && !is_jdk_version_initialized(), "must not initialize");
-    _jdk_version = 2;
-    _version_info.jdk_version = (1 << 24) | (2 << 16);
-  }
-  static void set_jdk13x_version() {
-    assert(_pre_jdk16_version && !is_jdk_version_initialized(), "must not initialize");
-    _jdk_version = 3;
-    _version_info.jdk_version = (1 << 24) | (3 << 16);
-  }
-  static void set_jdk14x_version() {
-    assert(_pre_jdk16_version && !is_jdk_version_initialized(), "must not initialize");
-    _jdk_version = 4;
-    _version_info.jdk_version = (1 << 24) | (4 << 16);
-  }
-  static void set_jdk15x_version() {
-    assert(_pre_jdk16_version && !is_jdk_version_initialized(), "must not initialize");
-    _jdk_version = 5;
-    _version_info.jdk_version = (1 << 24) | (5 << 16);
+    return current().compare_major(7) >= 0;
   }
 };