# HG changeset patch # User johnc # Date 1354216995 28800 # Node ID c24f778e94014483d1df3ec9ecf6577d4febd278 # Parent 59c7900749938c5ba985467efbb15ff81e83ff7e# Parent 2fc0334f613aef43d1b3e7101df43473dcd3fcc1 Merge diff -r 2fc0334f613a -r c24f778e9401 src/cpu/sparc/vm/frame_sparc.cpp --- 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 diff -r 2fc0334f613a -r c24f778e9401 src/cpu/x86/vm/frame_x86.cpp --- 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 diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp --- 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) \ - declare_type(AFLBinaryTreeDictionary, FreeBlockDictionary) \ - declare_type(AFLBinaryTreeDictionary, FreeBlockDictionary) \ + declare_type(AFLBinaryTreeDictionary, FreeBlockDictionary) #define VM_INT_CONSTANTS_CMS(declare_constant) \ declare_constant(Generation::ConcurrentMarkSweep) \ diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/gc_interface/collectedHeap.hpp --- 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; diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/gc_interface/collectedHeap.inline.hpp --- 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); diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/memory/allocation.cpp --- 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); } diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/memory/allocation.hpp --- 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 diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/memory/filemap.cpp --- 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 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; diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/memory/metaspace.cpp --- 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(); diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/memory/metaspace.hpp --- 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; diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/memory/universe.cpp --- 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; } diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/oops/compiledICHolder.cpp --- 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"); } diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/oops/method.cpp --- 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"); } diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/oops/method.hpp --- 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); diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/prims/forte.cpp --- 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 diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/prims/jni.cpp --- 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"); } } diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/prims/jvmti.xml --- 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)->GetStackTrace(jvmti, aThread, 0, 5, - &frames, &count); + frames, &count); if (err == JVMTI_ERROR_NONE && count >= 1) { char *methodName; err = (*jvmti)->GetMethodName(jvmti, frames[0].method, - &methodName, NULL); + &methodName, NULL, NULL); if (err == JVMTI_ERROR_NONE) { printf("Executing method: %s", methodName); } diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/runtime/vmStructs.cpp --- 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*) \ declare_toplevel_type(FreeList) \ declare_toplevel_type(MetablockTreeDictionary*) \ - declare_type(MetablockTreeDictionary, FreeBlockDictionary) \ - declare_type(MetablockTreeDictionary, FreeBlockDictionary) + declare_type(MetablockTreeDictionary, FreeBlockDictionary) /* 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 diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/runtime/vmStructs.hpp --- 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. diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/runtime/vm_version.cpp --- 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; } diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/services/memSnapshot.cpp --- 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; diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/services/memSnapshot.hpp --- 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; diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/services/memTracker.cpp --- 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); } } diff -r 2fc0334f613a -r c24f778e9401 src/share/vm/utilities/globalDefinitions.hpp --- 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