Tue, 11 Nov 2014 10:48:06 -0800
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
src/share/vm/prims/whitebox.cpp | file | annotate | diff | comparison | revisions | |
src/share/vm/runtime/os.cpp | file | annotate | diff | comparison | revisions | |
src/share/vm/services/mallocTracker.cpp | file | annotate | diff | comparison | revisions | |
src/share/vm/services/mallocTracker.hpp | file | annotate | diff | comparison | revisions | |
src/share/vm/services/mallocTracker.inline.hpp | file | annotate | diff | comparison | revisions | |
test/TEST.groups | file | annotate | diff | comparison | revisions | |
test/runtime/NMT/UnsafeMallocLimit.java | file | annotate | diff | comparison | revisions | |
test/runtime/NMT/UnsafeMallocLimit2.java | file | annotate | diff | comparison | revisions |
1.1 --- a/src/share/vm/prims/whitebox.cpp Tue Nov 11 10:46:07 2014 -0800 1.2 +++ b/src/share/vm/prims/whitebox.cpp Tue Nov 11 10:48:06 2014 -0800 1.3 @@ -300,7 +300,7 @@ 1.4 // NMT picks it up correctly 1.5 WB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size)) 1.6 jlong addr = 0; 1.7 - addr = (jlong)(uintptr_t)os::malloc(size, mtTest); 1.8 + addr = (jlong)(uintptr_t)os::malloc(size, mtTest); 1.9 return addr; 1.10 WB_END 1.11 1.12 @@ -309,7 +309,7 @@ 1.13 WB_ENTRY(jlong, WB_NMTMallocWithPseudoStack(JNIEnv* env, jobject o, jlong size, jint pseudo_stack)) 1.14 address pc = (address)(size_t)pseudo_stack; 1.15 NativeCallStack stack(&pc, 1); 1.16 - return (jlong)os::malloc(size, mtTest, stack); 1.17 + return (jlong)(uintptr_t)os::malloc(size, mtTest, stack); 1.18 WB_END 1.19 1.20 // Free the memory allocated by NMTAllocTest
2.1 --- a/src/share/vm/runtime/os.cpp Tue Nov 11 10:46:07 2014 -0800 2.2 +++ b/src/share/vm/runtime/os.cpp Tue Nov 11 10:48:06 2014 -0800 2.3 @@ -571,17 +571,6 @@ 2.4 NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1)); 2.5 NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size)); 2.6 2.7 -#if INCLUDE_NMT 2.8 - // NMT can not track malloc allocation size > MAX_MALLOC_SIZE, which is 2.9 - // (1GB - 1) on 32-bit system. It is not an issue on 64-bit system, where 2.10 - // MAX_MALLOC_SIZE = ((1 << 62) - 1). 2.11 - // VM code does not have such large malloc allocation. However, it can come 2.12 - // Unsafe call. 2.13 - if (MemTracker::tracking_level() >= NMT_summary && size > MAX_MALLOC_SIZE) { 2.14 - return NULL; 2.15 - } 2.16 -#endif 2.17 - 2.18 #ifdef ASSERT 2.19 // checking for the WatcherThread and crash_protection first 2.20 // since os::malloc can be called when the libjvm.{dll,so} is 2.21 @@ -652,12 +641,6 @@ 2.22 } 2.23 2.24 void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCallStack& stack) { 2.25 -#if INCLUDE_NMT 2.26 - // See comments in os::malloc() above 2.27 - if (MemTracker::tracking_level() >= NMT_summary && size > MAX_MALLOC_SIZE) { 2.28 - return NULL; 2.29 - } 2.30 -#endif 2.31 2.32 #ifndef ASSERT 2.33 NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
3.1 --- a/src/share/vm/services/mallocTracker.cpp Tue Nov 11 10:46:07 2014 -0800 3.2 +++ b/src/share/vm/services/mallocTracker.cpp Tue Nov 11 10:48:06 2014 -0800 3.3 @@ -72,7 +72,7 @@ 3.4 3.5 MallocMemorySummary::record_free(size(), flags()); 3.6 MallocMemorySummary::record_free_malloc_header(sizeof(MallocHeader)); 3.7 - if (tracking_level() == NMT_detail) { 3.8 + if (MemTracker::tracking_level() == NMT_detail) { 3.9 MallocSiteTable::deallocation_at(size(), _bucket_idx, _pos_idx); 3.10 } 3.11 } 3.12 @@ -128,36 +128,18 @@ 3.13 } 3.14 3.15 // Uses placement global new operator to initialize malloc header 3.16 - switch(level) { 3.17 - case NMT_off: 3.18 - return malloc_base; 3.19 - case NMT_minimal: { 3.20 - MallocHeader* hdr = ::new (malloc_base) MallocHeader(); 3.21 - break; 3.22 - } 3.23 - case NMT_summary: { 3.24 - assert(size <= MAX_MALLOC_SIZE, "malloc size overrun for NMT"); 3.25 - header = ::new (malloc_base) MallocHeader(size, flags); 3.26 - break; 3.27 - } 3.28 - case NMT_detail: { 3.29 - assert(size <= MAX_MALLOC_SIZE, "malloc size overrun for NMT"); 3.30 - header = ::new (malloc_base) MallocHeader(size, flags, stack); 3.31 - break; 3.32 - } 3.33 - default: 3.34 - ShouldNotReachHere(); 3.35 + 3.36 + if (level == NMT_off) { 3.37 + return malloc_base; 3.38 } 3.39 + 3.40 + header = ::new (malloc_base)MallocHeader(size, flags, stack, level); 3.41 memblock = (void*)((char*)malloc_base + sizeof(MallocHeader)); 3.42 3.43 // The alignment check: 8 bytes alignment for 32 bit systems. 3.44 // 16 bytes alignment for 64-bit systems. 3.45 assert(((size_t)memblock & (sizeof(size_t) * 2 - 1)) == 0, "Alignment check"); 3.46 3.47 - // Sanity check 3.48 - assert(get_memory_tracking_level(memblock) == level, 3.49 - "Wrong tracking level"); 3.50 - 3.51 #ifdef ASSERT 3.52 if (level > NMT_minimal) { 3.53 // Read back
4.1 --- a/src/share/vm/services/mallocTracker.hpp Tue Nov 11 10:46:07 2014 -0800 4.2 +++ b/src/share/vm/services/mallocTracker.hpp Tue Nov 11 10:48:06 2014 -0800 4.3 @@ -239,68 +239,46 @@ 4.4 4.5 class MallocHeader VALUE_OBJ_CLASS_SPEC { 4.6 #ifdef _LP64 4.7 - size_t _size : 62; 4.8 - size_t _level : 2; 4.9 + size_t _size : 64; 4.10 size_t _flags : 8; 4.11 size_t _pos_idx : 16; 4.12 size_t _bucket_idx: 40; 4.13 #define MAX_MALLOCSITE_TABLE_SIZE ((size_t)1 << 40) 4.14 #define MAX_BUCKET_LENGTH ((size_t)(1 << 16)) 4.15 -#define MAX_MALLOC_SIZE (((size_t)1 << 62) - 1) 4.16 #else 4.17 - size_t _size : 30; 4.18 - size_t _level : 2; 4.19 + size_t _size : 32; 4.20 size_t _flags : 8; 4.21 size_t _pos_idx : 8; 4.22 size_t _bucket_idx: 16; 4.23 #define MAX_MALLOCSITE_TABLE_SIZE ((size_t)(1 << 16)) 4.24 #define MAX_BUCKET_LENGTH ((size_t)(1 << 8)) 4.25 -// Max malloc size = 1GB - 1 on 32 bit system, such has total 4GB memory 4.26 -#define MAX_MALLOC_SIZE ((size_t)(1 << 30) - 1) 4.27 #endif // _LP64 4.28 4.29 public: 4.30 - // Summary tracking header 4.31 - MallocHeader(size_t size, MEMFLAGS flags) { 4.32 + MallocHeader(size_t size, MEMFLAGS flags, const NativeCallStack& stack, NMT_TrackingLevel level) { 4.33 assert(sizeof(MallocHeader) == sizeof(void*) * 2, 4.34 "Wrong header size"); 4.35 4.36 - _level = NMT_summary; 4.37 + if (level == NMT_minimal) { 4.38 + return; 4.39 + } 4.40 + 4.41 _flags = flags; 4.42 set_size(size); 4.43 + if (level == NMT_detail) { 4.44 + size_t bucket_idx; 4.45 + size_t pos_idx; 4.46 + if (record_malloc_site(stack, size, &bucket_idx, &pos_idx)) { 4.47 + assert(bucket_idx <= MAX_MALLOCSITE_TABLE_SIZE, "Overflow bucket index"); 4.48 + assert(pos_idx <= MAX_BUCKET_LENGTH, "Overflow bucket position index"); 4.49 + _bucket_idx = bucket_idx; 4.50 + _pos_idx = pos_idx; 4.51 + } 4.52 + } 4.53 + 4.54 MallocMemorySummary::record_malloc(size, flags); 4.55 MallocMemorySummary::record_new_malloc_header(sizeof(MallocHeader)); 4.56 } 4.57 - // Detail tracking header 4.58 - MallocHeader(size_t size, MEMFLAGS flags, const NativeCallStack& stack) { 4.59 - assert(sizeof(MallocHeader) == sizeof(void*) * 2, 4.60 - "Wrong header size"); 4.61 - 4.62 - _level = NMT_detail; 4.63 - _flags = flags; 4.64 - set_size(size); 4.65 - size_t bucket_idx; 4.66 - size_t pos_idx; 4.67 - if (record_malloc_site(stack, size, &bucket_idx, &pos_idx)) { 4.68 - assert(bucket_idx <= MAX_MALLOCSITE_TABLE_SIZE, "Overflow bucket index"); 4.69 - assert(pos_idx <= MAX_BUCKET_LENGTH, "Overflow bucket position index"); 4.70 - _bucket_idx = bucket_idx; 4.71 - _pos_idx = pos_idx; 4.72 - } 4.73 - MallocMemorySummary::record_malloc(size, flags); 4.74 - MallocMemorySummary::record_new_malloc_header(sizeof(MallocHeader)); 4.75 - } 4.76 - // Minimal tracking header 4.77 - MallocHeader() { 4.78 - assert(sizeof(MallocHeader) == sizeof(void*) * 2, 4.79 - "Wrong header size"); 4.80 - 4.81 - _level = (unsigned short)NMT_minimal; 4.82 - } 4.83 - 4.84 - inline NMT_TrackingLevel tracking_level() const { 4.85 - return (NMT_TrackingLevel)_level; 4.86 - } 4.87 4.88 inline size_t size() const { return _size; } 4.89 inline MEMFLAGS flags() const { return (MEMFLAGS)_flags; } 4.90 @@ -311,7 +289,6 @@ 4.91 4.92 private: 4.93 inline void set_size(size_t size) { 4.94 - assert(size <= MAX_MALLOC_SIZE, "Malloc size too large, should use virtual memory?"); 4.95 _size = size; 4.96 } 4.97 bool record_malloc_site(const NativeCallStack& stack, size_t size, 4.98 @@ -347,10 +324,6 @@ 4.99 // Record free on specified memory block 4.100 static void* record_free(void* memblock); 4.101 4.102 - // Get tracking level of specified memory block 4.103 - static inline NMT_TrackingLevel get_memory_tracking_level(void* memblock); 4.104 - 4.105 - 4.106 // Offset memory address to header address 4.107 static inline void* get_base(void* memblock); 4.108 static inline void* get_base(void* memblock, NMT_TrackingLevel level) { 4.109 @@ -361,16 +334,12 @@ 4.110 // Get memory size 4.111 static inline size_t get_size(void* memblock) { 4.112 MallocHeader* header = malloc_header(memblock); 4.113 - assert(header->tracking_level() >= NMT_summary, 4.114 - "Wrong tracking level"); 4.115 return header->size(); 4.116 } 4.117 4.118 // Get memory type 4.119 static inline MEMFLAGS get_flags(void* memblock) { 4.120 MallocHeader* header = malloc_header(memblock); 4.121 - assert(header->tracking_level() >= NMT_summary, 4.122 - "Wrong tracking level"); 4.123 return header->flags(); 4.124 } 4.125 4.126 @@ -394,7 +363,6 @@ 4.127 static inline MallocHeader* malloc_header(void *memblock) { 4.128 assert(memblock != NULL, "NULL pointer"); 4.129 MallocHeader* header = (MallocHeader*)((char*)memblock - sizeof(MallocHeader)); 4.130 - assert(header->tracking_level() >= NMT_minimal, "Bad header"); 4.131 return header; 4.132 } 4.133 };
5.1 --- a/src/share/vm/services/mallocTracker.inline.hpp Tue Nov 11 10:46:07 2014 -0800 5.2 +++ b/src/share/vm/services/mallocTracker.inline.hpp Tue Nov 11 10:48:06 2014 -0800 5.3 @@ -28,13 +28,6 @@ 5.4 #include "services/mallocTracker.hpp" 5.5 #include "services/memTracker.hpp" 5.6 5.7 -inline NMT_TrackingLevel MallocTracker::get_memory_tracking_level(void* memblock) { 5.8 - assert(memblock != NULL, "Sanity check"); 5.9 - if (MemTracker::tracking_level() == NMT_off) return NMT_off; 5.10 - MallocHeader* header = malloc_header(memblock); 5.11 - return header->tracking_level(); 5.12 -} 5.13 - 5.14 inline void* MallocTracker::get_base(void* memblock){ 5.15 return get_base(memblock, MemTracker::tracking_level()); 5.16 }
6.1 --- a/test/TEST.groups Tue Nov 11 10:46:07 2014 -0800 6.2 +++ b/test/TEST.groups Tue Nov 11 10:48:06 2014 -0800 6.3 @@ -90,7 +90,6 @@ 6.4 runtime/NMT/SummarySanityCheck.java \ 6.5 runtime/NMT/ThreadedMallocTestType.java \ 6.6 runtime/NMT/ThreadedVirtualAllocTestType.java \ 6.7 - runtime/NMT/UnsafeMallocLimit.java \ 6.8 runtime/NMT/VirtualAllocCommitUncommitRecommit.java \ 6.9 runtime/NMT/VirtualAllocTestType.java \ 6.10 runtime/RedefineObject/TestRedefineObject.java \
7.1 --- a/test/runtime/NMT/UnsafeMallocLimit.java Tue Nov 11 10:46:07 2014 -0800 7.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 7.3 @@ -1,50 +0,0 @@ 7.4 -/* 7.5 - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 7.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7.7 - * 7.8 - * This code is free software; you can redistribute it and/or modify it 7.9 - * under the terms of the GNU General Public License version 2 only, as 7.10 - * published by the Free Software Foundation. 7.11 - * 7.12 - * This code is distributed in the hope that it will be useful, but WITHOUT 7.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 7.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 7.15 - * version 2 for more details (a copy is included in the LICENSE file that 7.16 - * accompanied this code). 7.17 - * 7.18 - * You should have received a copy of the GNU General Public License version 7.19 - * 2 along with this work; if not, write to the Free Software Foundation, 7.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 7.21 - * 7.22 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 7.23 - * or visit www.oracle.com if you need additional information or have any 7.24 - * questions. 7.25 - */ 7.26 - 7.27 -/* 7.28 - * @test 7.29 - * @bug 8055289 7.30 - * @library /testlibrary 7.31 - * @build UnsafeMallocLimit 7.32 - * @run main/othervm -Xmx32m -XX:NativeMemoryTracking=summary UnsafeMallocLimit 7.33 - */ 7.34 - 7.35 -import com.oracle.java.testlibrary.*; 7.36 -import sun.misc.Unsafe; 7.37 - 7.38 -public class UnsafeMallocLimit { 7.39 - 7.40 - public static void main(String args[]) throws Exception { 7.41 - if (Platform.is32bit()) { 7.42 - Unsafe unsafe = Utils.getUnsafe(); 7.43 - try { 7.44 - unsafe.allocateMemory(1 << 30); 7.45 - throw new RuntimeException("Did not get expected OOME"); 7.46 - } catch (OutOfMemoryError e) { 7.47 - // Expected exception 7.48 - } 7.49 - } else { 7.50 - System.out.println("Test only valid on 32-bit platforms"); 7.51 - } 7.52 - } 7.53 -}
8.1 --- a/test/runtime/NMT/UnsafeMallocLimit2.java Tue Nov 11 10:46:07 2014 -0800 8.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 8.3 @@ -1,54 +0,0 @@ 8.4 -/* 8.5 - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 8.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 8.7 - * 8.8 - * This code is free software; you can redistribute it and/or modify it 8.9 - * under the terms of the GNU General Public License version 2 only, as 8.10 - * published by the Free Software Foundation. 8.11 - * 8.12 - * This code is distributed in the hope that it will be useful, but WITHOUT 8.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 8.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 8.15 - * version 2 for more details (a copy is included in the LICENSE file that 8.16 - * accompanied this code). 8.17 - * 8.18 - * You should have received a copy of the GNU General Public License version 8.19 - * 2 along with this work; if not, write to the Free Software Foundation, 8.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 8.21 - * 8.22 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 8.23 - * or visit www.oracle.com if you need additional information or have any 8.24 - * questions. 8.25 - */ 8.26 - 8.27 -/* 8.28 - * @test 8.29 - * @bug 8058818 8.30 - * @library /testlibrary 8.31 - * @build UnsafeMallocLimit2 8.32 - * @run main/othervm -Xmx32m -XX:NativeMemoryTracking=off UnsafeMallocLimit2 8.33 - */ 8.34 - 8.35 -import com.oracle.java.testlibrary.*; 8.36 -import sun.misc.Unsafe; 8.37 - 8.38 -public class UnsafeMallocLimit2 { 8.39 - 8.40 - public static void main(String args[]) throws Exception { 8.41 - if (Platform.is32bit()) { 8.42 - Unsafe unsafe = Utils.getUnsafe(); 8.43 - try { 8.44 - // Allocate greater than MALLOC_MAX and likely won't fail to allocate, 8.45 - // so it hits the NMT code that asserted. 8.46 - // Test that this doesn't cause an assertion with NMT off. 8.47 - // The option above overrides if all the tests are run with NMT on. 8.48 - unsafe.allocateMemory(0x40000000); 8.49 - System.out.println("Allocation succeeded"); 8.50 - } catch (OutOfMemoryError e) { 8.51 - System.out.println("Allocation failed"); 8.52 - } 8.53 - } else { 8.54 - System.out.println("Test only valid on 32-bit platforms"); 8.55 - } 8.56 - } 8.57 -}