# HG changeset patch # User ctornqvi # Date 1415731686 28800 # Node ID 787c9c28311f98cacc8bb27309395c5d84d12ec4 # Parent 09259e52a61017d933bec9f20a3439b5ed84af56 8058251: assert(_count > 0) failed: Negative counter when running runtime/NMT/MallocTrackingVerify.java Summary: Fixed an issue when overflowing the MallocSite hash table bucket Reviewed-by: coleenp, gtriantafill diff -r 09259e52a610 -r 787c9c28311f src/share/vm/prims/whitebox.cpp --- a/src/share/vm/prims/whitebox.cpp Tue Nov 11 10:46:07 2014 -0800 +++ b/src/share/vm/prims/whitebox.cpp Tue Nov 11 10:48:06 2014 -0800 @@ -300,7 +300,7 @@ // NMT picks it up correctly WB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size)) jlong addr = 0; - addr = (jlong)(uintptr_t)os::malloc(size, mtTest); + addr = (jlong)(uintptr_t)os::malloc(size, mtTest); return addr; WB_END @@ -309,7 +309,7 @@ WB_ENTRY(jlong, WB_NMTMallocWithPseudoStack(JNIEnv* env, jobject o, jlong size, jint pseudo_stack)) address pc = (address)(size_t)pseudo_stack; NativeCallStack stack(&pc, 1); - return (jlong)os::malloc(size, mtTest, stack); + return (jlong)(uintptr_t)os::malloc(size, mtTest, stack); WB_END // Free the memory allocated by NMTAllocTest diff -r 09259e52a610 -r 787c9c28311f src/share/vm/runtime/os.cpp --- a/src/share/vm/runtime/os.cpp Tue Nov 11 10:46:07 2014 -0800 +++ b/src/share/vm/runtime/os.cpp Tue Nov 11 10:48:06 2014 -0800 @@ -571,17 +571,6 @@ NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1)); NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size)); -#if INCLUDE_NMT - // NMT can not track malloc allocation size > MAX_MALLOC_SIZE, which is - // (1GB - 1) on 32-bit system. It is not an issue on 64-bit system, where - // MAX_MALLOC_SIZE = ((1 << 62) - 1). - // VM code does not have such large malloc allocation. However, it can come - // Unsafe call. - if (MemTracker::tracking_level() >= NMT_summary && size > MAX_MALLOC_SIZE) { - return NULL; - } -#endif - #ifdef ASSERT // checking for the WatcherThread and crash_protection first // since os::malloc can be called when the libjvm.{dll,so} is @@ -652,12 +641,6 @@ } void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCallStack& stack) { -#if INCLUDE_NMT - // See comments in os::malloc() above - if (MemTracker::tracking_level() >= NMT_summary && size > MAX_MALLOC_SIZE) { - return NULL; - } -#endif #ifndef ASSERT NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1)); diff -r 09259e52a610 -r 787c9c28311f src/share/vm/services/mallocTracker.cpp --- a/src/share/vm/services/mallocTracker.cpp Tue Nov 11 10:46:07 2014 -0800 +++ b/src/share/vm/services/mallocTracker.cpp Tue Nov 11 10:48:06 2014 -0800 @@ -72,7 +72,7 @@ MallocMemorySummary::record_free(size(), flags()); MallocMemorySummary::record_free_malloc_header(sizeof(MallocHeader)); - if (tracking_level() == NMT_detail) { + if (MemTracker::tracking_level() == NMT_detail) { MallocSiteTable::deallocation_at(size(), _bucket_idx, _pos_idx); } } @@ -128,36 +128,18 @@ } // Uses placement global new operator to initialize malloc header - switch(level) { - case NMT_off: - return malloc_base; - case NMT_minimal: { - MallocHeader* hdr = ::new (malloc_base) MallocHeader(); - break; - } - case NMT_summary: { - assert(size <= MAX_MALLOC_SIZE, "malloc size overrun for NMT"); - header = ::new (malloc_base) MallocHeader(size, flags); - break; - } - case NMT_detail: { - assert(size <= MAX_MALLOC_SIZE, "malloc size overrun for NMT"); - header = ::new (malloc_base) MallocHeader(size, flags, stack); - break; - } - default: - ShouldNotReachHere(); + + if (level == NMT_off) { + return malloc_base; } + + header = ::new (malloc_base)MallocHeader(size, flags, stack, level); memblock = (void*)((char*)malloc_base + sizeof(MallocHeader)); // The alignment check: 8 bytes alignment for 32 bit systems. // 16 bytes alignment for 64-bit systems. assert(((size_t)memblock & (sizeof(size_t) * 2 - 1)) == 0, "Alignment check"); - // Sanity check - assert(get_memory_tracking_level(memblock) == level, - "Wrong tracking level"); - #ifdef ASSERT if (level > NMT_minimal) { // Read back diff -r 09259e52a610 -r 787c9c28311f src/share/vm/services/mallocTracker.hpp --- a/src/share/vm/services/mallocTracker.hpp Tue Nov 11 10:46:07 2014 -0800 +++ b/src/share/vm/services/mallocTracker.hpp Tue Nov 11 10:48:06 2014 -0800 @@ -239,68 +239,46 @@ class MallocHeader VALUE_OBJ_CLASS_SPEC { #ifdef _LP64 - size_t _size : 62; - size_t _level : 2; + size_t _size : 64; size_t _flags : 8; size_t _pos_idx : 16; size_t _bucket_idx: 40; #define MAX_MALLOCSITE_TABLE_SIZE ((size_t)1 << 40) #define MAX_BUCKET_LENGTH ((size_t)(1 << 16)) -#define MAX_MALLOC_SIZE (((size_t)1 << 62) - 1) #else - size_t _size : 30; - size_t _level : 2; + size_t _size : 32; size_t _flags : 8; size_t _pos_idx : 8; size_t _bucket_idx: 16; #define MAX_MALLOCSITE_TABLE_SIZE ((size_t)(1 << 16)) #define MAX_BUCKET_LENGTH ((size_t)(1 << 8)) -// Max malloc size = 1GB - 1 on 32 bit system, such has total 4GB memory -#define MAX_MALLOC_SIZE ((size_t)(1 << 30) - 1) #endif // _LP64 public: - // Summary tracking header - MallocHeader(size_t size, MEMFLAGS flags) { - assert(sizeof(MallocHeader) == sizeof(void*) * 2, - "Wrong header size"); - - _level = NMT_summary; - _flags = flags; - set_size(size); - MallocMemorySummary::record_malloc(size, flags); - MallocMemorySummary::record_new_malloc_header(sizeof(MallocHeader)); - } - // Detail tracking header - MallocHeader(size_t size, MEMFLAGS flags, const NativeCallStack& stack) { + MallocHeader(size_t size, MEMFLAGS flags, const NativeCallStack& stack, NMT_TrackingLevel level) { assert(sizeof(MallocHeader) == sizeof(void*) * 2, "Wrong header size"); - _level = NMT_detail; + if (level == NMT_minimal) { + return; + } + _flags = flags; set_size(size); - size_t bucket_idx; - size_t pos_idx; - if (record_malloc_site(stack, size, &bucket_idx, &pos_idx)) { - assert(bucket_idx <= MAX_MALLOCSITE_TABLE_SIZE, "Overflow bucket index"); - assert(pos_idx <= MAX_BUCKET_LENGTH, "Overflow bucket position index"); - _bucket_idx = bucket_idx; - _pos_idx = pos_idx; + if (level == NMT_detail) { + size_t bucket_idx; + size_t pos_idx; + if (record_malloc_site(stack, size, &bucket_idx, &pos_idx)) { + assert(bucket_idx <= MAX_MALLOCSITE_TABLE_SIZE, "Overflow bucket index"); + assert(pos_idx <= MAX_BUCKET_LENGTH, "Overflow bucket position index"); + _bucket_idx = bucket_idx; + _pos_idx = pos_idx; + } } + MallocMemorySummary::record_malloc(size, flags); MallocMemorySummary::record_new_malloc_header(sizeof(MallocHeader)); } - // Minimal tracking header - MallocHeader() { - assert(sizeof(MallocHeader) == sizeof(void*) * 2, - "Wrong header size"); - - _level = (unsigned short)NMT_minimal; - } - - inline NMT_TrackingLevel tracking_level() const { - return (NMT_TrackingLevel)_level; - } inline size_t size() const { return _size; } inline MEMFLAGS flags() const { return (MEMFLAGS)_flags; } @@ -311,7 +289,6 @@ private: inline void set_size(size_t size) { - assert(size <= MAX_MALLOC_SIZE, "Malloc size too large, should use virtual memory?"); _size = size; } bool record_malloc_site(const NativeCallStack& stack, size_t size, @@ -347,10 +324,6 @@ // Record free on specified memory block static void* record_free(void* memblock); - // Get tracking level of specified memory block - static inline NMT_TrackingLevel get_memory_tracking_level(void* memblock); - - // Offset memory address to header address static inline void* get_base(void* memblock); static inline void* get_base(void* memblock, NMT_TrackingLevel level) { @@ -361,16 +334,12 @@ // Get memory size static inline size_t get_size(void* memblock) { MallocHeader* header = malloc_header(memblock); - assert(header->tracking_level() >= NMT_summary, - "Wrong tracking level"); return header->size(); } // Get memory type static inline MEMFLAGS get_flags(void* memblock) { MallocHeader* header = malloc_header(memblock); - assert(header->tracking_level() >= NMT_summary, - "Wrong tracking level"); return header->flags(); } @@ -394,7 +363,6 @@ static inline MallocHeader* malloc_header(void *memblock) { assert(memblock != NULL, "NULL pointer"); MallocHeader* header = (MallocHeader*)((char*)memblock - sizeof(MallocHeader)); - assert(header->tracking_level() >= NMT_minimal, "Bad header"); return header; } }; diff -r 09259e52a610 -r 787c9c28311f src/share/vm/services/mallocTracker.inline.hpp --- a/src/share/vm/services/mallocTracker.inline.hpp Tue Nov 11 10:46:07 2014 -0800 +++ b/src/share/vm/services/mallocTracker.inline.hpp Tue Nov 11 10:48:06 2014 -0800 @@ -28,13 +28,6 @@ #include "services/mallocTracker.hpp" #include "services/memTracker.hpp" -inline NMT_TrackingLevel MallocTracker::get_memory_tracking_level(void* memblock) { - assert(memblock != NULL, "Sanity check"); - if (MemTracker::tracking_level() == NMT_off) return NMT_off; - MallocHeader* header = malloc_header(memblock); - return header->tracking_level(); -} - inline void* MallocTracker::get_base(void* memblock){ return get_base(memblock, MemTracker::tracking_level()); } diff -r 09259e52a610 -r 787c9c28311f test/TEST.groups --- a/test/TEST.groups Tue Nov 11 10:46:07 2014 -0800 +++ b/test/TEST.groups Tue Nov 11 10:48:06 2014 -0800 @@ -90,7 +90,6 @@ runtime/NMT/SummarySanityCheck.java \ runtime/NMT/ThreadedMallocTestType.java \ runtime/NMT/ThreadedVirtualAllocTestType.java \ - runtime/NMT/UnsafeMallocLimit.java \ runtime/NMT/VirtualAllocCommitUncommitRecommit.java \ runtime/NMT/VirtualAllocTestType.java \ runtime/RedefineObject/TestRedefineObject.java \ diff -r 09259e52a610 -r 787c9c28311f test/runtime/NMT/UnsafeMallocLimit.java --- a/test/runtime/NMT/UnsafeMallocLimit.java Tue Nov 11 10:46:07 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 8055289 - * @library /testlibrary - * @build UnsafeMallocLimit - * @run main/othervm -Xmx32m -XX:NativeMemoryTracking=summary UnsafeMallocLimit - */ - -import com.oracle.java.testlibrary.*; -import sun.misc.Unsafe; - -public class UnsafeMallocLimit { - - public static void main(String args[]) throws Exception { - if (Platform.is32bit()) { - Unsafe unsafe = Utils.getUnsafe(); - try { - unsafe.allocateMemory(1 << 30); - throw new RuntimeException("Did not get expected OOME"); - } catch (OutOfMemoryError e) { - // Expected exception - } - } else { - System.out.println("Test only valid on 32-bit platforms"); - } - } -} diff -r 09259e52a610 -r 787c9c28311f test/runtime/NMT/UnsafeMallocLimit2.java --- a/test/runtime/NMT/UnsafeMallocLimit2.java Tue Nov 11 10:46:07 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 8058818 - * @library /testlibrary - * @build UnsafeMallocLimit2 - * @run main/othervm -Xmx32m -XX:NativeMemoryTracking=off UnsafeMallocLimit2 - */ - -import com.oracle.java.testlibrary.*; -import sun.misc.Unsafe; - -public class UnsafeMallocLimit2 { - - public static void main(String args[]) throws Exception { - if (Platform.is32bit()) { - Unsafe unsafe = Utils.getUnsafe(); - try { - // Allocate greater than MALLOC_MAX and likely won't fail to allocate, - // so it hits the NMT code that asserted. - // Test that this doesn't cause an assertion with NMT off. - // The option above overrides if all the tests are run with NMT on. - unsafe.allocateMemory(0x40000000); - System.out.println("Allocation succeeded"); - } catch (OutOfMemoryError e) { - System.out.println("Allocation failed"); - } - } else { - System.out.println("Test only valid on 32-bit platforms"); - } - } -}