changeset 7182:c24f778e9401

Merge
author johnc
date Thu, 29 Nov 2012 11:23:15 -0800
parents 59c790074993 (diff) 2fc0334f613a (current diff)
children 5505fbbae3d3
files src/share/vm/gc_interface/collectedHeap.inline.hpp src/share/vm/memory/universe.cpp src/share/vm/prims/jni.cpp src/share/vm/runtime/vmStructs.cpp
diffstat 24 files changed, 165 insertions(+), 115 deletions(-) [+]
line wrap: on
line diff
--- a/src/cpu/sparc/vm/frame_sparc.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/cpu/sparc/vm/frame_sparc.cpp	Thu Nov 29 11:23:15 2012 -0800
@@ -648,7 +648,7 @@
   Method* m = *interpreter_frame_method_addr();
 
   // validate the method we'd find in this potential sender
-  if (!Universe::heap()->is_valid_method(m)) return false;
+  if (!m->is_valid_method()) return false;
 
   // stack frames shouldn't be much larger than max_stack elements
 
--- a/src/cpu/x86/vm/frame_x86.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/cpu/x86/vm/frame_x86.cpp	Thu Nov 29 11:23:15 2012 -0800
@@ -534,7 +534,7 @@
   Method* m = *interpreter_frame_method_addr();
 
   // validate the method we'd find in this potential sender
-  if (!Universe::heap()->is_valid_method(m)) return false;
+  if (!m->is_valid_method()) return false;
 
   // stack frames shouldn't be much larger than max_stack elements
 
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp	Thu Nov 29 11:23:15 2012 -0800
@@ -65,8 +65,7 @@
   declare_toplevel_type(AFLBinaryTreeDictionary*)                         \
   declare_toplevel_type(LinearAllocBlock)                                 \
   declare_toplevel_type(FreeBlockDictionary<FreeChunk>)                   \
-  declare_type(AFLBinaryTreeDictionary, FreeBlockDictionary<FreeChunk>)   \
-            declare_type(AFLBinaryTreeDictionary, FreeBlockDictionary<FreeChunk>) \
+           declare_type(AFLBinaryTreeDictionary, FreeBlockDictionary<FreeChunk>)
 
 #define VM_INT_CONSTANTS_CMS(declare_constant)                            \
   declare_constant(Generation::ConcurrentMarkSweep)                       \
--- a/src/share/vm/gc_interface/collectedHeap.hpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/gc_interface/collectedHeap.hpp	Thu Nov 29 11:23:15 2012 -0800
@@ -289,11 +289,6 @@
   // (A scavenge is a GC which is not a full GC.)
   virtual bool is_scavengable(const void *p) = 0;
 
-  // Returns "TRUE" if "p" is a method oop in the
-  // current heap, with high probability. This predicate
-  // is not stable, in general.
-  bool is_valid_method(Method* p) const;
-
   void set_gc_cause(GCCause::Cause v) {
      if (UsePerfData) {
        _gc_lastcause = _gc_cause;
--- a/src/share/vm/gc_interface/collectedHeap.inline.hpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/gc_interface/collectedHeap.inline.hpp	Thu Nov 29 11:23:15 2012 -0800
@@ -230,36 +230,6 @@
   return (oop)obj;
 }
 
-// Returns "TRUE" if "p" is a method oop in the
-// current heap with high probability. NOTE: The main
-// current consumers of this interface are Forte::
-// and ThreadProfiler::. In these cases, the
-// interpreter frame from which "p" came, may be
-// under construction when sampled asynchronously, so
-// the clients want to check that it represents a
-// valid method before using it. Nonetheless since
-// the clients do not typically lock out GC, the
-// predicate is_valid_method() is not stable, so
-// it is possible that by the time "p" is used, it
-// is no longer valid.
-inline bool CollectedHeap::is_valid_method(Method* p) const {
-  return
-    p != NULL &&
-
-    // Check whether "method" is metadata
-    p->is_metadata() &&
-
-    // See if GC is active; however, there is still an
-    // apparently unavoidable window after this call
-    // and before the client of this interface uses "p".
-    // If the client chooses not to lock out GC, then
-    // it's a risk the client must accept.
-    !is_gc_active() &&
-
-    // Check that p is a Method*.
-    p->is_method();
-}
-
 inline void CollectedHeap::oop_iterate_no_header(OopClosure* cl) {
   NoHeaderExtendedOopClosure no_header_cl(cl);
   oop_iterate(&no_header_cl);
--- a/src/share/vm/memory/allocation.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/memory/allocation.cpp	Thu Nov 29 11:23:15 2012 -0800
@@ -66,10 +66,17 @@
 }
 
 bool MetaspaceObj::is_metadata() const {
-  // ClassLoaderDataGraph::contains((address)this); has lock inversion problems
+  // GC Verify checks use this in guarantees.
+  // TODO: either replace them with is_metaspace_object() or remove them.
+  // is_metaspace_object() is slower than this test.  This test doesn't
+  // seem very useful for metaspace objects anymore though.
   return !Universe::heap()->is_in_reserved(this);
 }
 
+bool MetaspaceObj::is_metaspace_object() const {
+  return Metaspace::contains((void*)this);
+}
+
 void MetaspaceObj::print_address_on(outputStream* st) const {
   st->print(" {"INTPTR_FORMAT"}", this);
 }
--- a/src/share/vm/memory/allocation.hpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/memory/allocation.hpp	Thu Nov 29 11:23:15 2012 -0800
@@ -245,6 +245,7 @@
 class MetaspaceObj {
  public:
   bool is_metadata() const;
+  bool is_metaspace_object() const;  // more specific test but slower
   bool is_shared() const;
   void print_address_on(outputStream* st) const;  // nonvirtual address printing
 
--- a/src/share/vm/memory/filemap.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/memory/filemap.cpp	Thu Nov 29 11:23:15 2012 -0800
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "classfile/classLoader.hpp"
 #include "classfile/symbolTable.hpp"
+#include "classfile/altHashing.hpp"
 #include "memory/filemap.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/java.hpp"
@@ -82,8 +83,37 @@
   close();
 }
 
+// Fill in the fileMapInfo structure with data about this VM instance.
 
-// Fill in the fileMapInfo structure with data about this VM instance.
+// This method copies the vm version info into header_version.  If the version is too
+// long then a truncated version, which has a hash code appended to it, is copied.
+//
+// Using a template enables this method to verify that header_version is an array of
+// length JVM_IDENT_MAX.  This ensures that the code that writes to the CDS file and
+// the code that reads the CDS file will both use the same size buffer.  Hence, will
+// use identical truncation.  This is necessary for matching of truncated versions.
+template <int N> static void get_header_version(char (&header_version) [N]) {
+  assert(N == JVM_IDENT_MAX, "Bad header_version size");
+
+  const char *vm_version = VM_Version::internal_vm_info_string();
+  const int version_len = (int)strlen(vm_version);
+
+  if (version_len < (JVM_IDENT_MAX-1)) {
+    strcpy(header_version, vm_version);
+
+  } else {
+    // Get the hash value.  Use a static seed because the hash needs to return the same
+    // value over multiple jvm invocations.
+    unsigned int hash = AltHashing::murmur3_32(8191, (const jbyte*)vm_version, version_len);
+
+    // Truncate the ident, saving room for the 8 hex character hash value.
+    strncpy(header_version, vm_version, JVM_IDENT_MAX-9);
+
+    // Append the hash code as eight hex digits.
+    sprintf(&header_version[JVM_IDENT_MAX-9], "%08x", hash);
+    header_version[JVM_IDENT_MAX-1] = 0;  // Null terminate.
+  }
+}
 
 void FileMapInfo::populate_header(size_t alignment) {
   _header._magic = 0xf00baba2;
@@ -95,13 +125,7 @@
   // invoked with.
 
   // JVM version string ... changes on each build.
-  const char *vm_version = VM_Version::internal_vm_info_string();
-  if (strlen(vm_version) < (JVM_IDENT_MAX-1)) {
-    strcpy(_header._jvm_ident, vm_version);
-  } else {
-    fail_stop("JVM Ident field for shared archive is too long"
-              " - truncated to <%s>", _header._jvm_ident);
-  }
+  get_header_version(_header._jvm_ident);
 
   // Build checks on classpath and jar files
   _header._num_jars = 0;
@@ -434,8 +458,9 @@
     fail_continue("The shared archive file has a bad magic number.");
     return false;
   }
-  if (strncmp(_header._jvm_ident, VM_Version::internal_vm_info_string(),
-              JVM_IDENT_MAX-1) != 0) {
+  char header_version[JVM_IDENT_MAX];
+  get_header_version(header_version);
+  if (strncmp(_header._jvm_ident, header_version, JVM_IDENT_MAX-1) != 0) {
     fail_continue("The shared archive file was created by a different"
                   " version or build of HotSpot.");
     return false;
--- a/src/share/vm/memory/metaspace.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/memory/metaspace.cpp	Thu Nov 29 11:23:15 2012 -0800
@@ -36,6 +36,7 @@
 #include "memory/universe.hpp"
 #include "runtime/globals.hpp"
 #include "runtime/mutex.hpp"
+#include "runtime/orderAccess.hpp"
 #include "services/memTracker.hpp"
 #include "utilities/copy.hpp"
 #include "utilities/debug.hpp"
@@ -1007,6 +1008,8 @@
     delete new_entry;
     return false;
   } else {
+    // ensure lock-free iteration sees fully initialized node
+    OrderAccess::storestore();
     link_vs(new_entry, vs_word_size);
     return true;
   }
@@ -1096,7 +1099,6 @@
   }
 }
 
-#ifndef PRODUCT
 bool VirtualSpaceList::contains(const void *ptr) {
   VirtualSpaceNode* list = virtual_space_list();
   VirtualSpaceListIterator iter(list);
@@ -1108,7 +1110,6 @@
   }
   return false;
 }
-#endif // PRODUCT
 
 
 // MetaspaceGC methods
@@ -2739,15 +2740,17 @@
   }
 }
 
-#ifndef PRODUCT
-bool Metaspace::contains(const void * ptr) const {
+bool Metaspace::contains(const void * ptr) {
   if (MetaspaceShared::is_in_shared_space(ptr)) {
     return true;
   }
-  MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag);
+  // This is checked while unlocked.  As long as the virtualspaces are added
+  // at the end, the pointer will be in one of them.  The virtual spaces
+  // aren't deleted presently.  When they are, some sort of locking might
+  // be needed.  Note, locking this can cause inversion problems with the
+  // caller in MetaspaceObj::is_metadata() function.
   return space_list()->contains(ptr) || class_space_list()->contains(ptr);
 }
-#endif
 
 void Metaspace::verify() {
   vsm()->verify();
--- a/src/share/vm/memory/metaspace.hpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/memory/metaspace.hpp	Thu Nov 29 11:23:15 2012 -0800
@@ -135,11 +135,7 @@
 
   static bool is_initialized() { return _class_space_list != NULL; }
 
-#ifndef PRODUCT
-  bool contains(const void *ptr) const;
-  bool contains_class(const void *ptr) const;
-#endif
-
+  static bool contains(const void *ptr);
   void dump(outputStream* const out) const;
 
   void print_on(outputStream* st) const;
--- a/src/share/vm/memory/universe.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/memory/universe.cpp	Thu Nov 29 11:23:15 2012 -0800
@@ -414,14 +414,10 @@
 // from MetaspaceObj, because the latter does not have virtual functions.
 // If the metadata type has a vtable, it cannot be shared in the read-only
 // section of the CDS archive, because the vtable pointer is patched.
-static inline void* dereference(void* addr) {
-  return *(void**)addr;
-}
-
 static inline void add_vtable(void** list, int* n, void* o, int count) {
   guarantee((*n) < count, "vtable list too small");
-  void* vtable = dereference(o);
-  assert(dereference(vtable) != NULL, "invalid vtable");
+  void* vtable = dereference_vptr(o);
+  assert(*(void**)(vtable) != NULL, "invalid vtable");
   list[(*n)++] = vtable;
 }
 
--- a/src/share/vm/oops/compiledICHolder.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/oops/compiledICHolder.cpp	Thu Nov 29 11:23:15 2012 -0800
@@ -48,8 +48,8 @@
 // Verification
 
 void CompiledICHolder::verify_on(outputStream* st) {
-  guarantee(holder_method()->is_metadata(),   "should be in permspace");
+  guarantee(holder_method()->is_metadata(),   "should be in metaspace");
   guarantee(holder_method()->is_method(), "should be method");
-  guarantee(holder_klass()->is_metadata(),    "should be in permspace");
+  guarantee(holder_klass()->is_metadata(),    "should be in metaspace");
   guarantee(holder_klass()->is_klass(),   "should be klass");
 }
--- a/src/share/vm/oops/method.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/oops/method.cpp	Thu Nov 29 11:23:15 2012 -0800
@@ -1814,6 +1814,23 @@
   loader_data->jmethod_ids()->clear_all_methods();
 }
 
+
+// Check that this pointer is valid by checking that the vtbl pointer matches
+bool Method::is_valid_method() const {
+  if (this == NULL) {
+    return false;
+  } else if (!is_metaspace_object()) {
+    return false;
+  } else {
+    Method m;
+    // This assumes that the vtbl pointer is the first word of a C++ object.
+    // This assumption is also in universe.cpp patch_klass_vtble
+    void* vtbl2 = dereference_vptr((void*)&m);
+    void* this_vtbl = dereference_vptr((void*)this);
+    return vtbl2 == this_vtbl;
+  }
+}
+
 #ifndef PRODUCT
 void Method::print_jmethod_ids(ClassLoaderData* loader_data, outputStream* out) {
   out->print_cr("jni_method_id count = %d", loader_data->jmethod_ids()->count_methods());
@@ -1935,7 +1952,7 @@
   guarantee(constMethod()->is_metadata(), "should be metadata");
   MethodData* md = method_data();
   guarantee(md == NULL ||
-      md->is_metadata(), "should be in permspace");
+      md->is_metadata(), "should be metadata");
   guarantee(md == NULL ||
       md->is_methodData(), "should be method data");
 }
--- a/src/share/vm/oops/method.hpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/oops/method.hpp	Thu Nov 29 11:23:15 2012 -0800
@@ -169,7 +169,8 @@
                           ConstMethod::MethodType method_type,
                           TRAPS);
 
-  Method() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
+  // CDS and vtbl checking can create an empty Method to get vtbl pointer.
+  Method(){}
 
   // The Method vtable is restored by this call when the Method is in the
   // shared archive.  See patch_klass_vtables() in metaspaceShared.cpp for
@@ -812,6 +813,9 @@
 
   const char* internal_name() const { return "{method}"; }
 
+  // Check for valid method pointer
+  bool is_valid_method() const;
+
   // Verify
   void verify() { verify_on(tty); }
   void verify_on(outputStream* st);
--- a/src/share/vm/prims/forte.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/prims/forte.cpp	Thu Nov 29 11:23:15 2012 -0800
@@ -216,10 +216,7 @@
     // not yet valid.
 
     *method_p = method;
-
-    // See if gc may have invalidated method since we validated frame
-
-    if (!Universe::heap()->is_valid_method(method)) return false;
+    if (!method->is_valid_method()) return false;
 
     intptr_t bcx = fr->interpreter_frame_bcx();
 
@@ -394,19 +391,11 @@
   bool fully_decipherable = find_initial_Java_frame(thd, &top_frame, &initial_Java_frame, &method, &bci);
 
   // The frame might not be walkable but still recovered a method
-  // (e.g. an nmethod with no scope info for the pc
+  // (e.g. an nmethod with no scope info for the pc)
 
   if (method == NULL) return;
 
-  CollectedHeap* ch = Universe::heap();
-
-  // The method is not stored GC safe so see if GC became active
-  // after we entered AsyncGetCallTrace() and before we try to
-  // use the Method*.
-  // Yes, there is still a window after this check and before
-  // we use Method* below, but we can't lock out GC so that
-  // has to be an acceptable risk.
-  if (!ch->is_valid_method(method)) {
+  if (!method->is_valid_method()) {
     trace->num_frames = ticks_GC_active; // -2
     return;
   }
@@ -440,13 +429,7 @@
     bci = st.bci();
     method = st.method();
 
-    // The method is not stored GC safe so see if GC became active
-    // after we entered AsyncGetCallTrace() and before we try to
-    // use the Method*.
-    // Yes, there is still a window after this check and before
-    // we use Method* below, but we can't lock out GC so that
-    // has to be an acceptable risk.
-    if (!ch->is_valid_method(method)) {
+    if (!method->is_valid_method()) {
       // we throw away everything we've gathered in this sample since
       // none of it is safe
       trace->num_frames = ticks_GC_active; // -2
--- a/src/share/vm/prims/jni.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/prims/jni.cpp	Thu Nov 29 11:23:15 2012 -0800
@@ -5041,6 +5041,9 @@
 
 #include "gc_interface/collectedHeap.hpp"
 #include "utilities/quickSort.hpp"
+#if INCLUDE_VM_STRUCTS
+#include "runtime/vmStructs.hpp"
+#endif
 
 #define run_unit_test(unit_test_function_call)              \
   tty->print_cr("Running test: " #unit_test_function_call); \
@@ -5053,6 +5056,9 @@
     run_unit_test(CollectedHeap::test_is_in());
     run_unit_test(QuickSort::test_quick_sort());
     run_unit_test(AltHashing::test_alt_hash());
+#if INCLUDE_VM_STRUCTS
+    run_unit_test(VMStructs::test());
+#endif
     tty->print_cr("All internal VM tests passed");
   }
 }
--- a/src/share/vm/prims/jvmti.xml	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/prims/jvmti.xml	Thu Nov 29 11:23:15 2012 -0800
@@ -2370,11 +2370,11 @@
 jvmtiError err;
 
 err = (*jvmti)-&gt;GetStackTrace(jvmti, aThread, 0, 5, 
-                               &amp;frames, &amp;count);
+                               frames, &amp;count);
 if (err == JVMTI_ERROR_NONE &amp;&amp; count &gt;= 1) {
    char *methodName;
    err = (*jvmti)-&gt;GetMethodName(jvmti, frames[0].method, 
-                       &amp;methodName, NULL);
+                       &amp;methodName, NULL, NULL);
    if (err == JVMTI_ERROR_NONE) {
       printf("Executing method: %s", methodName);
    }
--- a/src/share/vm/runtime/vmStructs.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/runtime/vmStructs.cpp	Thu Nov 29 11:23:15 2012 -0800
@@ -2096,8 +2096,7 @@
   declare_toplevel_type(FreeList<Metablock>*)                             \
   declare_toplevel_type(FreeList<Metablock>)                              \
   declare_toplevel_type(MetablockTreeDictionary*)                         \
-  declare_type(MetablockTreeDictionary, FreeBlockDictionary<Metablock>)   \
-              declare_type(MetablockTreeDictionary, FreeBlockDictionary<Metablock>)
+           declare_type(MetablockTreeDictionary, FreeBlockDictionary<Metablock>)
 
 
   /* NOTE that we do not use the last_entry() macro here; it is used  */
@@ -3204,3 +3203,17 @@
 void vmStructs_init() {
   debug_only(VMStructs::init());
 }
+
+#ifndef PRODUCT
+void VMStructs::test() {
+  // Check for duplicate entries in type array
+  for (int i = 0; localHotSpotVMTypes[i].typeName != NULL; i++) {
+    for (int j = i + 1; localHotSpotVMTypes[j].typeName != NULL; j++) {
+      if (strcmp(localHotSpotVMTypes[i].typeName, localHotSpotVMTypes[j].typeName) == 0) {
+        tty->print_cr("Duplicate entries for '%s'", localHotSpotVMTypes[i].typeName);
+        assert(false, "Duplicate types in localHotSpotVMTypes array");
+      }
+    }
+  }
+}
+#endif
--- a/src/share/vm/runtime/vmStructs.hpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/runtime/vmStructs.hpp	Thu Nov 29 11:23:15 2012 -0800
@@ -123,6 +123,11 @@
   // the data structure (debug build only)
   static void init();
 
+#ifndef PRODUCT
+  // Execute unit tests
+  static void test();
+#endif
+
 private:
   // Look up a type in localHotSpotVMTypes using strcmp() (debug build only).
   // Returns 1 if found, 0 if not.
--- a/src/share/vm/runtime/vm_version.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/runtime/vm_version.cpp	Thu Nov 29 11:23:15 2012 -0800
@@ -243,19 +243,21 @@
 
   #ifndef FLOAT_ARCH
     #if defined(__SOFTFP__)
-      #define FLOAT_ARCH "-sflt"
+      #define FLOAT_ARCH_STR "-sflt"
     #elif defined(E500V2)
-      #define FLOAT_ARCH "-e500v2"
+      #define FLOAT_ARCH_STR "-e500v2"
     #elif defined(ARM)
-      #define FLOAT_ARCH "-vfp"
+      #define FLOAT_ARCH_STR "-vfp"
     #elif defined(PPC)
-      #define FLOAT_ARCH "-hflt"
+      #define FLOAT_ARCH_STR "-hflt"
     #else
-      #define FLOAT_ARCH ""
+      #define FLOAT_ARCH_STR ""
     #endif
+  #else
+    #define FLOAT_ARCH_STR XSTR(FLOAT_ARCH)
   #endif
 
-  return VMNAME " (" VM_RELEASE ") for " OS "-" CPU FLOAT_ARCH
+  return VMNAME " (" VM_RELEASE ") for " OS "-" CPU FLOAT_ARCH_STR
          " JRE (" JRE_RELEASE_VERSION "), built on " __DATE__ " " __TIME__
          " by " XSTR(HOTSPOT_BUILD_USER) " with " HOTSPOT_BUILD_COMPILER;
 }
--- a/src/share/vm/services/memSnapshot.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/services/memSnapshot.cpp	Thu Nov 29 11:23:15 2012 -0800
@@ -261,17 +261,19 @@
   VMMemRegion* cur = (VMMemRegion*)current();
   assert(cur->is_reserved_region() && cur->contains_region(rec),
     "Sanity check");
+  if (rec->is_same_region(cur)) {
+    // release whole reserved region
 #ifdef ASSERT
-  VMMemRegion* next_reg = (VMMemRegion*)peek_next();
-  // should not have any committed memory in this reserved region
-  assert(next_reg == NULL || !next_reg->is_committed_region(), "Sanity check");
+    VMMemRegion* next_region = (VMMemRegion*)peek_next();
+    // should not have any committed memory in this reserved region
+    assert(next_region == NULL || !next_region->is_committed_region(), "Sanity check");
 #endif
-  if (rec->is_same_region(cur)) {
     remove();
   } else if (rec->addr() == cur->addr() ||
     rec->addr() + rec->size() == cur->addr() + cur->size()) {
     // released region is at either end of this region
     cur->exclude_region(rec->addr(), rec->size());
+    assert(check_reserved_region(), "Integrity check");
   } else { // split the reserved region and release the middle
     address high_addr = cur->addr() + cur->size();
     size_t sz = high_addr - rec->addr();
@@ -280,10 +282,14 @@
     if (MemTracker::track_callsite()) {
       MemPointerRecordEx tmp(rec->addr() + rec->size(), cur->flags(), sz,
         ((VMMemRegionEx*)cur)->pc());
-      return insert_reserved_region(&tmp);
+      bool ret = insert_reserved_region(&tmp);
+      assert(!ret || check_reserved_region(), "Integrity check");
+      return ret;
     } else {
       MemPointerRecord tmp(rec->addr() + rec->size(), cur->flags(), sz);
-      return insert_reserved_region(&tmp);
+      bool ret = insert_reserved_region(&tmp);
+      assert(!ret || check_reserved_region(), "Integrity check");
+      return ret;
     }
   }
   return true;
--- a/src/share/vm/services/memSnapshot.hpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/services/memSnapshot.hpp	Thu Nov 29 11:23:15 2012 -0800
@@ -146,6 +146,23 @@
   // reset current position
   inline void reset() { _pos = 0; }
 #ifdef ASSERT
+  // check integrity of records on current reserved memory region.
+  bool check_reserved_region() {
+    VMMemRegion* reserved_region = (VMMemRegion*)current();
+    assert(reserved_region != NULL && reserved_region->is_reserved_region(),
+          "Sanity check");
+    // all committed regions that follow current reserved region, should all
+    // belong to the reserved region.
+    VMMemRegion* next_region = (VMMemRegion*)next();
+    for (; next_region != NULL && next_region->is_committed_region();
+         next_region = (VMMemRegion*)next() ) {
+      if(!reserved_region->contains_region(next_region)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
   virtual bool is_dup_pointer(const MemPointer* ptr1,
     const MemPointer* ptr2) const {
     VMMemRegion* p1 = (VMMemRegion*)ptr1;
--- a/src/share/vm/services/memTracker.cpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/services/memTracker.cpp	Thu Nov 29 11:23:15 2012 -0800
@@ -69,15 +69,12 @@
 
 void MemTracker::init_tracking_options(const char* option_line) {
   _tracking_level = NMT_off;
-  if (strncmp(option_line, "=summary", 8) == 0) {
+  if (strcmp(option_line, "=summary") == 0) {
     _tracking_level = NMT_summary;
-  } else if (strncmp(option_line, "=detail", 7) == 0) {
+  } else if (strcmp(option_line, "=detail") == 0) {
     _tracking_level = NMT_detail;
-  } else {
-    char msg[255];
-    //+1 to remove the '=' character
-    jio_snprintf(msg, 255, "Unknown option given to XX:NativeMemoryTracking: %s", option_line+1);
-    vm_exit_during_initialization(msg, NULL);
+  } else if (strcmp(option_line, "=off") != 0) {
+    vm_exit_during_initialization("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]", NULL);
   }
 }
 
--- a/src/share/vm/utilities/globalDefinitions.hpp	Tue Nov 27 14:11:37 2012 -0800
+++ b/src/share/vm/utilities/globalDefinitions.hpp	Thu Nov 29 11:23:15 2012 -0800
@@ -1280,4 +1280,12 @@
 
 #define ARRAY_SIZE(array) (sizeof(array)/sizeof((array)[0]))
 
+// Dereference vptr
+// All C++ compilers that we know of have the vtbl pointer in the first
+// word.  If there are exceptions, this function needs to be made compiler
+// specific.
+static inline void* dereference_vptr(void* addr) {
+  return *(void**)addr;
+}
+
 #endif // SHARE_VM_UTILITIES_GLOBALDEFINITIONS_HPP