Mercurial > hg > truffle
changeset 7187:5fafdef522c6
Merge
author | johnc |
---|---|
date | Fri, 30 Nov 2012 12:01:34 -0800 |
parents | 5505fbbae3d3 (diff) dad48145e775 (current diff) |
children | b61d9c88b759 |
files | src/share/vm/classfile/classFileParser.cpp src/share/vm/memory/metaspace.cpp src/share/vm/memory/metaspace.hpp src/share/vm/memory/universe.cpp |
diffstat | 34 files changed, 309 insertions(+), 185 deletions(-) [+] |
line wrap: on
line diff
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java Thu Nov 29 23:02:52 2012 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java Fri Nov 30 12:01:34 2012 -0800 @@ -48,6 +48,7 @@ private static int HAS_CHECKED_EXCEPTIONS; private static int HAS_LOCALVARIABLE_TABLE; private static int HAS_EXCEPTION_TABLE; + private static int HAS_GENERIC_SIGNATURE; private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { Type type = db.lookupType("ConstMethod"); @@ -60,13 +61,14 @@ HAS_CHECKED_EXCEPTIONS = db.lookupIntConstant("ConstMethod::_has_checked_exceptions").intValue(); HAS_LOCALVARIABLE_TABLE = db.lookupIntConstant("ConstMethod::_has_localvariable_table").intValue(); HAS_EXCEPTION_TABLE = db.lookupIntConstant("ConstMethod::_has_exception_table").intValue(); + HAS_GENERIC_SIGNATURE = db.lookupIntConstant("ConstMethod::_has_generic_signature").intValue(); // Size of Java bytecodes allocated immediately after ConstMethod*. codeSize = new CIntField(type.getCIntegerField("_code_size"), 0); nameIndex = new CIntField(type.getCIntegerField("_name_index"), 0); signatureIndex = new CIntField(type.getCIntegerField("_signature_index"), 0); - genericSignatureIndex = new CIntField(type.getCIntegerField("_generic_signature_index"),0); idnum = new CIntField(type.getCIntegerField("_method_idnum"), 0); + maxStack = new CIntField(type.getCIntegerField("_max_stack"), 0); // start of byte code bytecodeOffset = type.getSize(); @@ -92,8 +94,8 @@ private static CIntField codeSize; private static CIntField nameIndex; private static CIntField signatureIndex; - private static CIntField genericSignatureIndex; private static CIntField idnum; + private static CIntField maxStack; // start of bytecode private static long bytecodeOffset; @@ -134,13 +136,21 @@ } public long getGenericSignatureIndex() { - return genericSignatureIndex.getValue(this); + if (hasGenericSignature()) { + return getAddress().getCIntegerAt(offsetOfGenericSignatureIndex(), 2, true); + } else { + return 0; + } } public long getIdNum() { return idnum.getValue(this); } + public long getMaxStack() { + return maxStack.getValue(this); + } + public Symbol getName() { return getMethod().getName(); } @@ -235,8 +245,8 @@ visitor.doCInt(codeSize, true); visitor.doCInt(nameIndex, true); visitor.doCInt(signatureIndex, true); - visitor.doCInt(genericSignatureIndex, true); visitor.doCInt(codeSize, true); + visitor.doCInt(maxStack, true); } // Accessors @@ -353,6 +363,10 @@ return ret; } + private boolean hasGenericSignature() { + return (getFlags() & HAS_GENERIC_SIGNATURE) != 0; + } + //--------------------------------------------------------------------------- // Internals only below this point @@ -377,8 +391,14 @@ return getSize() * VM.getVM().getObjectHeap().getOopSize() - 2; } + // Offset of the generic signature index + private long offsetOfGenericSignatureIndex() { + return offsetOfLastU2Element(); + } + private long offsetOfCheckedExceptionsLength() { - return offsetOfLastU2Element(); + return hasGenericSignature() ? offsetOfLastU2Element() - 2 : + offsetOfLastU2Element(); } private int getCheckedExceptionsLength() { @@ -431,7 +451,8 @@ } else if (hasCheckedExceptions()) { return offsetOfCheckedExceptions() - 2; } else { - return offsetOfLastU2Element(); + return hasGenericSignature() ? offsetOfLastU2Element() - 2 : + offsetOfLastU2Element(); } } @@ -460,7 +481,8 @@ if (hasCheckedExceptions()) { return offsetOfCheckedExceptions() - 2; } else { - return offsetOfLastU2Element(); + return hasGenericSignature() ? offsetOfLastU2Element() - 2 : + offsetOfLastU2Element(); } }
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java Thu Nov 29 23:02:52 2012 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java Fri Nov 30 12:01:34 2012 -0800 @@ -50,7 +50,6 @@ constMethod = type.getAddressField("_constMethod"); methodData = type.getAddressField("_method_data"); methodSize = new CIntField(type.getCIntegerField("_method_size"), 0); - maxStack = new CIntField(type.getCIntegerField("_max_stack"), 0); maxLocals = new CIntField(type.getCIntegerField("_max_locals"), 0); sizeOfParameters = new CIntField(type.getCIntegerField("_size_of_parameters"), 0); accessFlags = new CIntField(type.getCIntegerField("_access_flags"), 0); @@ -84,7 +83,6 @@ private static AddressField constMethod; private static AddressField methodData; private static CIntField methodSize; - private static CIntField maxStack; private static CIntField maxLocals; private static CIntField sizeOfParameters; private static CIntField accessFlags; @@ -135,7 +133,7 @@ } /** WARNING: this is in words, not useful in this system; use getObjectSize() instead */ public long getMethodSize() { return methodSize.getValue(this); } - public long getMaxStack() { return maxStack.getValue(this); } + public long getMaxStack() { return getConstMethod().getMaxStack(); } public long getMaxLocals() { return maxLocals.getValue(this); } public long getSizeOfParameters() { return sizeOfParameters.getValue(this); } public long getNameIndex() { return getConstMethod().getNameIndex(); } @@ -284,7 +282,6 @@ public void iterateFields(MetadataVisitor visitor) { visitor.doCInt(methodSize, true); - visitor.doCInt(maxStack, true); visitor.doCInt(maxLocals, true); visitor.doCInt(sizeOfParameters, true); visitor.doCInt(accessFlags, true);
--- a/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Thu Nov 29 23:02:52 2012 +0100 +++ b/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Fri Nov 30 12:01:34 2012 -0800 @@ -1048,7 +1048,6 @@ const Address constMethod (G5_method, 0, in_bytes(Method::const_offset())); const Address access_flags (G5_method, 0, in_bytes(Method::access_flags_offset())); const Address size_of_parameters(G5_method, 0, in_bytes(Method::size_of_parameters_offset())); - const Address max_stack (G5_method, 0, in_bytes(Method::max_stack_offset())); const Address size_of_locals (G5_method, 0, in_bytes(Method::size_of_locals_offset())); // slop factor is two extra slots on the expression stack so that @@ -1070,7 +1069,9 @@ __ lduh( size_of_parameters, Gtmp ); __ calc_mem_param_words(Gtmp, Gtmp); // space for native call parameters passed on the stack in words } else { - __ lduh(max_stack, Gtmp); // Full size expression stack + // Full size expression stack + __ ld_ptr(constMethod, Gtmp); + __ lduh(Gtmp, in_bytes(ConstMethod::max_stack_offset()), Gtmp); } __ add(Gtmp, fixed_size, Gtmp); // plus the fixed portion @@ -1206,7 +1207,9 @@ __ sub(O2, wordSize, O2); // prepush __ st_ptr(O2, XXX_STATE(_stack)); // PREPUSH - __ lduh(max_stack, O3); // Full size expression stack + // Full size expression stack + __ ld_ptr(constMethod, O3); + __ lduh(O3, in_bytes(ConstMethod::max_stack_offset()), O3); guarantee(!EnableInvokeDynamic, "no support yet for java.lang.invoke.MethodHandle"); //6815692 //6815692//if (EnableInvokeDynamic) //6815692// __ inc(O3, Method::extra_stack_entries()); @@ -1539,7 +1542,6 @@ const Address constMethod (G5_method, 0, in_bytes(Method::const_offset())); const Address access_flags (G5_method, 0, in_bytes(Method::access_flags_offset())); const Address size_of_parameters(G5_method, 0, in_bytes(Method::size_of_parameters_offset())); - const Address max_stack (G5_method, 0, in_bytes(Method::max_stack_offset())); const Address size_of_locals (G5_method, 0, in_bytes(Method::size_of_locals_offset())); address entry_point = __ pc();
--- a/src/cpu/sparc/vm/frame_sparc.cpp Thu Nov 29 23:02:52 2012 +0100 +++ b/src/cpu/sparc/vm/frame_sparc.cpp Fri Nov 30 12:01:34 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/sparc/vm/interp_masm_sparc.cpp Thu Nov 29 23:02:52 2012 +0100 +++ b/src/cpu/sparc/vm/interp_masm_sparc.cpp Fri Nov 30 12:01:34 2012 -0800 @@ -518,7 +518,8 @@ delayed()->nop(); // Compute max expression stack+register save area - lduh(Lmethod, in_bytes(Method::max_stack_offset()), Gframe_size); // Load max stack. + ld_ptr(Lmethod, in_bytes(Method::const_offset()), Gframe_size); + lduh(Gframe_size, in_bytes(ConstMethod::max_stack_offset()), Gframe_size); // Load max stack. add( Gframe_size, frame::memory_parameter_word_sp_offset, Gframe_size ); //
--- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Thu Nov 29 23:02:52 2012 +0100 +++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Fri Nov 30 12:01:34 2012 -0800 @@ -496,7 +496,7 @@ const Address size_of_parameters(G5_method, Method::size_of_parameters_offset()); const Address size_of_locals (G5_method, Method::size_of_locals_offset()); - const Address max_stack (G5_method, Method::max_stack_offset()); + const Address constMethod (G5_method, Method::const_offset()); int rounded_vm_local_words = round_to( frame::interpreter_frame_vm_local_words, WordsPerLong ); const int extra_space = @@ -538,7 +538,8 @@ // see if the frame is greater than one page in size. If so, // then we need to verify there is enough stack space remaining // Frame_size = (max_stack + extra_space) * BytesPerWord; - __ lduh( max_stack, Gframe_size ); + __ ld_ptr( constMethod, Gframe_size ); + __ lduh( Gframe_size, in_bytes(ConstMethod::max_stack_offset()), Gframe_size ); __ add( Gframe_size, extra_space, Gframe_size ); __ round_to( Gframe_size, WordsPerLong ); __ sll( Gframe_size, Interpreter::logStackElementSize, Gframe_size);
--- a/src/cpu/x86/vm/cppInterpreter_x86.cpp Thu Nov 29 23:02:52 2012 +0100 +++ b/src/cpu/x86/vm/cppInterpreter_x86.cpp Fri Nov 30 12:01:34 2012 -0800 @@ -538,9 +538,9 @@ // compute full expression stack limit - const Address size_of_stack (rbx, Method::max_stack_offset()); const int extra_stack = 0; //6815692//Method::extra_stack_words(); - __ load_unsigned_short(rdx, size_of_stack); // get size of expression stack in words + __ movptr(rdx, Address(rbx, Method::const_offset())); + __ load_unsigned_short(rdx, Address(rdx, ConstMethod::max_stack_offset())); // get size of expression stack in words __ negptr(rdx); // so we can subtract in next step // Allocate expression stack __ lea(rsp, Address(rsp, rdx, Address::times_ptr, -extra_stack)); @@ -682,12 +682,12 @@ const Address stack_size(thread, Thread::stack_size_offset()); // locals + overhead, in bytes - const Address size_of_stack (rbx, Method::max_stack_offset()); - // Always give one monitor to allow us to start interp if sync method. - // Any additional monitors need a check when moving the expression stack - const int one_monitor = frame::interpreter_frame_monitor_size() * wordSize; - const int extra_stack = 0; //6815692//Method::extra_stack_entries(); - __ load_unsigned_short(rax, size_of_stack); // get size of expression stack in words + // Always give one monitor to allow us to start interp if sync method. + // Any additional monitors need a check when moving the expression stack + const int one_monitor = frame::interpreter_frame_monitor_size() * wordSize; + const int extra_stack = 0; //6815692//Method::extra_stack_entries(); + __ movptr(rax, Address(rbx, Method::const_offset())); + __ load_unsigned_short(rax, Address(rax, ConstMethod::max_stack_offset())); // get size of expression stack in words __ lea(rax, Address(noreg, rax, Interpreter::stackElementScale(), extra_stack + one_monitor)); __ lea(rax, Address(rax, rdx, Interpreter::stackElementScale(), overhead_size));
--- a/src/cpu/x86/vm/frame_x86.cpp Thu Nov 29 23:02:52 2012 +0100 +++ b/src/cpu/x86/vm/frame_x86.cpp Fri Nov 30 12:01:34 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/classfile/classFileParser.cpp Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/classfile/classFileParser.cpp Fri Nov 30 12:01:34 2012 -0800 @@ -2184,7 +2184,7 @@ Method* m = Method::allocate( loader_data, code_length, access_flags, linenumber_table_length, total_lvt_length, exception_table_length, checked_exceptions_length, - ConstMethod::NORMAL, CHECK_(nullHandle)); + generic_signature_index, ConstMethod::NORMAL, CHECK_(nullHandle)); ClassLoadingService::add_class_method_size(m->size()*HeapWordSize); @@ -2192,7 +2192,6 @@ m->set_constants(cp()); m->set_name_index(name_index); m->set_signature_index(signature_index); - m->set_generic_signature_index(generic_signature_index); #ifdef CC_INTERP // hmm is there a gc issue here?? ResultTypeFinder rtf(cp->symbol_at(signature_index));
--- a/src/share/vm/classfile/defaultMethods.cpp Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/classfile/defaultMethods.cpp Fri Nov 30 12:01:34 2012 -0800 @@ -1148,12 +1148,11 @@ int code_length = bytecodes->length(); Method* m = Method::allocate(cp->pool_holder()->class_loader_data(), - code_length, flags, 0, 0, 0, 0, mt, CHECK_NULL); + code_length, flags, 0, 0, 0, 0, 0, mt, CHECK_NULL); m->set_constants(NULL); // This will get filled in later m->set_name_index(cp->utf8(name)); m->set_signature_index(cp->utf8(sig)); - m->set_generic_signature_index(0); #ifdef CC_INTERP ResultTypeFinder rtf(sig); m->set_result_index(rtf.type());
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp Fri Nov 30 12:01:34 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 Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/gc_interface/collectedHeap.hpp Fri Nov 30 12:01:34 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 Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/gc_interface/collectedHeap.inline.hpp Fri Nov 30 12:01:34 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 Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/memory/allocation.cpp Fri Nov 30 12:01:34 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 Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/memory/allocation.hpp Fri Nov 30 12:01:34 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 Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/memory/filemap.cpp Fri Nov 30 12:01:34 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 Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/memory/metaspace.cpp Fri Nov 30 12:01:34 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" @@ -1010,6 +1011,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; } @@ -1099,7 +1102,6 @@ } } -#ifndef PRODUCT bool VirtualSpaceList::contains(const void *ptr) { VirtualSpaceNode* list = virtual_space_list(); VirtualSpaceListIterator iter(list); @@ -1111,7 +1113,6 @@ } return false; } -#endif // PRODUCT // MetaspaceGC methods @@ -2755,15 +2756,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 Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/memory/metaspace.hpp Fri Nov 30 12:01:34 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 Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/memory/universe.cpp Fri Nov 30 12:01:34 2012 -0800 @@ -418,14 +418,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 Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/oops/compiledICHolder.cpp Fri Nov 30 12:01:34 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/constMethod.cpp Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/oops/constMethod.cpp Fri Nov 30 12:01:34 2012 -0800 @@ -39,16 +39,19 @@ int localvariable_table_length, int exception_table_length, int checked_exceptions_length, + u2 generic_signature_index, MethodType method_type, TRAPS) { int size = ConstMethod::size(byte_code_size, compressed_line_number_size, localvariable_table_length, exception_table_length, - checked_exceptions_length); + checked_exceptions_length, + generic_signature_index); return new (loader_data, size, true, THREAD) ConstMethod( byte_code_size, compressed_line_number_size, localvariable_table_length, - exception_table_length, checked_exceptions_length, method_type, size); + exception_table_length, checked_exceptions_length, generic_signature_index, + method_type, size); } ConstMethod::ConstMethod(int byte_code_size, @@ -56,6 +59,7 @@ int localvariable_table_length, int exception_table_length, int checked_exceptions_length, + u2 generic_signature_index, MethodType method_type, int size) { @@ -66,7 +70,8 @@ set_stackmap_data(NULL); set_code_size(byte_code_size); set_constMethod_size(size); - set_inlined_tables_length(checked_exceptions_length, + set_inlined_tables_length(generic_signature_index, + checked_exceptions_length, compressed_line_number_size, localvariable_table_length, exception_table_length); @@ -90,7 +95,8 @@ int compressed_line_number_size, int local_variable_table_length, int exception_table_length, - int checked_exceptions_length) { + int checked_exceptions_length, + u2 generic_signature_index) { int extra_bytes = code_size; if (compressed_line_number_size > 0) { extra_bytes += compressed_line_number_size; @@ -108,6 +114,9 @@ extra_bytes += sizeof(u2); extra_bytes += exception_table_length * sizeof(ExceptionTableElement); } + if (generic_signature_index != 0) { + extra_bytes += sizeof(u2); + } int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord; return align_object_size(header_size() + extra_words); } @@ -125,10 +134,17 @@ return code_end(); } -u2* ConstMethod::checked_exceptions_length_addr() const { +u2* ConstMethod::generic_signature_index_addr() const { // Located at the end of the constMethod. + assert(has_generic_signature(), "called only if generic signature exists"); + return last_u2_element(); +} + +u2* ConstMethod::checked_exceptions_length_addr() const { + // Located immediately before the generic signature index. assert(has_checked_exceptions(), "called only if table is present"); - return last_u2_element(); + return has_generic_signature() ? (last_u2_element() - 1) : + last_u2_element(); } u2* ConstMethod::exception_table_length_addr() const { @@ -137,8 +153,10 @@ // If checked_exception present, locate immediately before them. return (u2*) checked_exceptions_start() - 1; } else { - // Else, the exception table is at the end of the constMethod. - return last_u2_element(); + // Else, the exception table is at the end of the constMethod or + // immediately before the generic signature index. + return has_generic_signature() ? (last_u2_element() - 1) : + last_u2_element(); } } @@ -152,25 +170,30 @@ // If checked_exception present, locate immediately before them. return (u2*) checked_exceptions_start() - 1; } else { - // Else, the linenumber table is at the end of the constMethod. - return last_u2_element(); + // Else, the linenumber table is at the end of the constMethod or + // immediately before the generic signature index. + return has_generic_signature() ? (last_u2_element() - 1) : + last_u2_element(); } } } - // Update the flags to indicate the presence of these optional fields. -void ConstMethod::set_inlined_tables_length( - int checked_exceptions_len, - int compressed_line_number_size, - int localvariable_table_len, - int exception_table_len) { +void ConstMethod::set_inlined_tables_length(u2 generic_signature_index, + int checked_exceptions_len, + int compressed_line_number_size, + int localvariable_table_len, + int exception_table_len) { // Must be done in the order below, otherwise length_addr accessors // will not work. Only set bit in header if length is positive. assert(_flags == 0, "Error"); if (compressed_line_number_size > 0) { _flags |= _has_linenumber_table; } + if (generic_signature_index != 0) { + _flags |= _has_generic_signature; + *(generic_signature_index_addr()) = generic_signature_index; + } if (checked_exceptions_len > 0) { _flags |= _has_checked_exceptions; *(checked_exceptions_length_addr()) = checked_exceptions_len;
--- a/src/share/vm/oops/constMethod.hpp Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/oops/constMethod.hpp Fri Nov 30 12:01:34 2012 -0800 @@ -45,7 +45,7 @@ // | constMethod_size | // | interp_kind | flags | code_size | // | name index | signature index | -// | method_idnum | generic_signature_index | +// | method_idnum | max_stack | // |------------------------------------------------------| // | | // | byte codes | @@ -55,26 +55,29 @@ // | (see class CompressedLineNumberReadStream) | // | (note that length is unknown until decompressed) | // | (access flags bit tells whether table is present) | -// | (indexed from start of ConstMethod*) | +// | (indexed from start of ConstMethod*) | // | (elements not necessarily sorted!) | // |------------------------------------------------------| // | localvariable table elements + length (length last) | // | (length is u2, elements are 6-tuples of u2) | // | (see class LocalVariableTableElement) | // | (access flags bit tells whether table is present) | -// | (indexed from end of ConstMethod*) | +// | (indexed from end of ConstMethod*) | // |------------------------------------------------------| // | exception table + length (length last) | // | (length is u2, elements are 4-tuples of u2) | // | (see class ExceptionTableElement) | // | (access flags bit tells whether table is present) | -// | (indexed from end of ConstMethod*) | +// | (indexed from end of ConstMethod*) | // |------------------------------------------------------| // | checked exceptions elements + length (length last) | // | (length is u2, elements are u2) | // | (see class CheckedExceptionElement) | // | (access flags bit tells whether table is present) | -// | (indexed from end of ConstMethod*) | +// | (indexed from end of ConstMethod*) | +// |------------------------------------------------------| +// | generic signature index (u2) | +// | (indexed from start of constMethodOop) | // |------------------------------------------------------| @@ -118,7 +121,8 @@ _has_checked_exceptions = 2, _has_localvariable_table = 4, _has_exception_table = 8, - _is_overpass = 16 + _has_generic_signature = 16, + _is_overpass = 32 }; // Bit vector of signature @@ -145,7 +149,7 @@ u2 _method_idnum; // unique identification number for the method within the class // initially corresponds to the index into the methods array. // but this may change with redefinition - u2 _generic_signature_index; // Generic signature (index in constant pool, 0 if absent) + u2 _max_stack; // Maximum number of entries on the expression stack // Constructor @@ -154,6 +158,7 @@ int localvariable_table_length, int exception_table_length, int checked_exceptions_length, + u2 generic_signature_index, MethodType is_overpass, int size); public: @@ -164,17 +169,22 @@ int localvariable_table_length, int exception_table_length, int checked_exceptions_length, + u2 generic_signature_index, MethodType mt, TRAPS); bool is_constMethod() const { return true; } // Inlined tables - void set_inlined_tables_length(int checked_exceptions_len, + void set_inlined_tables_length(u2 generic_signature_index, + int checked_exceptions_len, int compressed_line_number_size, int localvariable_table_len, int exception_table_len); + bool has_generic_signature() const + { return (_flags & _has_generic_signature) != 0; } + bool has_linenumber_table() const { return (_flags & _has_linenumber_table) != 0; } @@ -252,8 +262,18 @@ void set_signature_index(int index) { _signature_index = index; } // generics support - int generic_signature_index() const { return _generic_signature_index; } - void set_generic_signature_index(int index) { _generic_signature_index = index; } + int generic_signature_index() const { + if (has_generic_signature()) { + return *generic_signature_index_addr(); + } else { + return 0; + } + } + void set_generic_signature_index(u2 index) { + assert(has_generic_signature(), ""); + u2* addr = generic_signature_index_addr(); + *addr = index; + } // Sizing static int header_size() { @@ -264,7 +284,8 @@ static int size(int code_size, int compressed_line_number_size, int local_variable_table_length, int exception_table_length, - int checked_exceptions_length); + int checked_exceptions_length, + u2 generic_signature_index); int size() const { return _constMethod_size;} void set_constMethod_size(int size) { _constMethod_size = size; } @@ -281,6 +302,7 @@ // linenumber table - note that length is unknown until decompression, // see class CompressedLineNumberReadStream. u_char* compressed_linenumber_table() const; // not preserved by gc + u2* generic_signature_index_addr() const; u2* checked_exceptions_length_addr() const; u2* localvariable_table_length_addr() const; u2* exception_table_length_addr() const; @@ -314,12 +336,19 @@ static ByteSize constants_offset() { return byte_offset_of(ConstMethod, _constants); } + static ByteSize max_stack_offset() + { return byte_offset_of(ConstMethod, _max_stack); } + // Unique id for the method static const u2 MAX_IDNUM; static const u2 UNSET_IDNUM; u2 method_idnum() const { return _method_idnum; } void set_method_idnum(u2 idnum) { _method_idnum = idnum; } + // max stack + int max_stack() const { return _max_stack; } + void set_max_stack(int size) { _max_stack = size; } + // Deallocation for RedefineClasses void deallocate_contents(ClassLoaderData* loader_data); bool is_klass() const { return false; }
--- a/src/share/vm/oops/method.cpp Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/oops/method.cpp Fri Nov 30 12:01:34 2012 -0800 @@ -64,6 +64,7 @@ int localvariable_table_length, int exception_table_length, int checked_exceptions_length, + u2 generic_signature_index, ConstMethod::MethodType method_type, TRAPS) { assert(!access_flags.is_native() || byte_code_size == 0, @@ -74,6 +75,7 @@ localvariable_table_length, exception_table_length, checked_exceptions_length, + generic_signature_index, method_type, CHECK_NULL); @@ -1034,7 +1036,7 @@ methodHandle m; { Method* m_oop = Method::allocate(loader_data, 0, accessFlags_from(flags_bits), - 0, 0, 0, 0, ConstMethod::NORMAL, CHECK_(empty)); + 0, 0, 0, 0, 0, ConstMethod::NORMAL, CHECK_(empty)); m = methodHandle(THREAD, m_oop); } m->set_constants(cp()); @@ -1082,6 +1084,7 @@ assert(!m->is_native(), "cannot rewrite native methods"); // Allocate new Method* AccessFlags flags = m->access_flags(); + u2 generic_signature_index = m->generic_signature_index(); int checked_exceptions_len = m->checked_exceptions_length(); int localvariable_len = m->localvariable_table_length(); int exception_table_len = m->exception_table_length(); @@ -1094,6 +1097,7 @@ localvariable_len, exception_table_len, checked_exceptions_len, + generic_signature_index, m->method_type(), CHECK_(methodHandle())); methodHandle newm (THREAD, newm_oop); @@ -1814,6 +1818,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 +1956,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 Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/oops/method.hpp Fri Nov 30 12:01:34 2012 -0800 @@ -73,12 +73,10 @@ // |------------------------------------------------------| // | result_index (C++ interpreter only) | // |------------------------------------------------------| -// | method_size | max_stack | -// | max_locals | size_of_parameters | +// | method_size | max_locals | +// | size_of_parameters | intrinsic_id| flags | // |------------------------------------------------------| -// |intrinsic_id| flags | throwout_count | -// |------------------------------------------------------| -// | num_breakpoints | (unused) | +// | throwout_count | num_breakpoints | // |------------------------------------------------------| // | invocation_counter | // | backedge_counter | @@ -118,7 +116,6 @@ int _result_index; // C++ interpreter needs for converting results to/from stack #endif u2 _method_size; // size of this object - u2 _max_stack; // Maximum number of entries on the expression stack u2 _max_locals; // Number of local variables used by this method u2 _size_of_parameters; // size of the parameter block (receiver + arguments) in words u1 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none) @@ -166,10 +163,12 @@ int localvariable_table_length, int exception_table_length, int checked_exceptions_length, + u2 generic_signature_index, 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 @@ -288,9 +287,9 @@ // max stack // return original max stack size for method verification - int verifier_max_stack() const { return _max_stack; } - int max_stack() const { return _max_stack + extra_stack_entries(); } - void set_max_stack(int size) { _max_stack = size; } + int verifier_max_stack() const { return constMethod()->max_stack(); } + int max_stack() const { return constMethod()->max_stack() + extra_stack_entries(); } + void set_max_stack(int size) { constMethod()->set_max_stack(size); } // max locals int max_locals() const { return _max_locals; } @@ -606,7 +605,6 @@ static ByteSize from_interpreted_offset() { return byte_offset_of(Method, _from_interpreted_entry ); } static ByteSize interpreter_entry_offset() { return byte_offset_of(Method, _i2i_entry ); } static ByteSize signature_handler_offset() { return in_ByteSize(sizeof(Method) + wordSize); } - static ByteSize max_stack_offset() { return byte_offset_of(Method, _max_stack ); } // for code generation static int method_data_offset_in_bytes() { return offset_of(Method, _method_data); } @@ -812,6 +810,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 Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/prims/forte.cpp Fri Nov 30 12:01:34 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 Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/prims/jni.cpp Fri Nov 30 12:01:34 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 Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/prims/jvmti.xml Fri Nov 30 12:01:34 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); }
--- a/src/share/vm/runtime/vmStructs.cpp Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/runtime/vmStructs.cpp Fri Nov 30 12:01:34 2012 -0800 @@ -355,7 +355,6 @@ nonstatic_field(Method, _access_flags, AccessFlags) \ nonstatic_field(Method, _vtable_index, int) \ nonstatic_field(Method, _method_size, u2) \ - nonstatic_field(Method, _max_stack, u2) \ nonstatic_field(Method, _max_locals, u2) \ nonstatic_field(Method, _size_of_parameters, u2) \ nonstatic_field(Method, _interpreter_throwout_count, u2) \ @@ -378,7 +377,7 @@ nonstatic_field(ConstMethod, _name_index, u2) \ nonstatic_field(ConstMethod, _signature_index, u2) \ nonstatic_field(ConstMethod, _method_idnum, u2) \ - nonstatic_field(ConstMethod, _generic_signature_index, u2) \ + nonstatic_field(ConstMethod, _max_stack, u2) \ nonstatic_field(ObjArrayKlass, _element_klass, Klass*) \ nonstatic_field(ObjArrayKlass, _bottom_klass, Klass*) \ volatile_nonstatic_field(Symbol, _refcount, int) \ @@ -2096,8 +2095,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 */ @@ -2281,6 +2279,7 @@ declare_constant(ConstMethod::_has_checked_exceptions) \ declare_constant(ConstMethod::_has_localvariable_table) \ declare_constant(ConstMethod::_has_exception_table) \ + declare_constant(ConstMethod::_has_generic_signature) \ \ /*************************************/ \ /* InstanceKlass enum */ \ @@ -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 Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/runtime/vmStructs.hpp Fri Nov 30 12:01:34 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 Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/runtime/vm_version.cpp Fri Nov 30 12:01:34 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 Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/services/memSnapshot.cpp Fri Nov 30 12:01:34 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 Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/services/memSnapshot.hpp Fri Nov 30 12:01:34 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 Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/services/memTracker.cpp Fri Nov 30 12:01:34 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 Thu Nov 29 23:02:52 2012 +0100 +++ b/src/share/vm/utilities/globalDefinitions.hpp Fri Nov 30 12:01:34 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