8058251: assert(_count > 0) failed: Negative counter when running runtime/NMT/MallocTrackingVerify.java

Tue, 11 Nov 2014 10:48:06 -0800

author
ctornqvi
date
Tue, 11 Nov 2014 10:48:06 -0800
changeset 7344
787c9c28311f
parent 7343
09259e52a610
child 7345
a28b7832203a

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 -}

mercurial