8029106: JVM crashes in Metachunk::Metachunk during parallel class redefinition (PrivateMLetController, anonymous-simple_copy_1)

Mon, 09 Dec 2013 10:03:39 +0100

author
stefank
date
Mon, 09 Dec 2013 10:03:39 +0100
changeset 6170
fa76dce60db7
parent 6169
ad72068ac41e
child 6171
e3995ab44393

8029106: JVM crashes in Metachunk::Metachunk during parallel class redefinition (PrivateMLetController, anonymous-simple_copy_1)
Summary: Fixed overflow bug in VirtualSpaceNode::is_available
Reviewed-by: mgerdin, brutisso, coleenp, jmasa

src/share/vm/memory/metaspace.cpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/memory/metaspace.cpp	Tue Dec 10 10:31:00 2013 +0100
     1.2 +++ b/src/share/vm/memory/metaspace.cpp	Mon Dec 09 10:03:39 2013 +0100
     1.3 @@ -287,7 +287,7 @@
     1.4    VirtualSpace* virtual_space() const { return (VirtualSpace*) &_virtual_space; }
     1.5  
     1.6    // Returns true if "word_size" is available in the VirtualSpace
     1.7 -  bool is_available(size_t word_size) { return _top + word_size <= end(); }
     1.8 +  bool is_available(size_t word_size) { return word_size <= pointer_delta(end(), _top, sizeof(MetaWord)); }
     1.9  
    1.10    MetaWord* top() const { return _top; }
    1.11    void inc_top(size_t word_size) { _top += word_size; }
    1.12 @@ -3641,10 +3641,82 @@
    1.13      }
    1.14  
    1.15    }
    1.16 +
    1.17 +#define assert_is_available_positive(word_size) \
    1.18 +  assert(vsn.is_available(word_size), \
    1.19 +    err_msg(#word_size ": " PTR_FORMAT " bytes were not available in " \
    1.20 +            "VirtualSpaceNode [" PTR_FORMAT ", " PTR_FORMAT ")", \
    1.21 +            (uintptr_t)(word_size * BytesPerWord), vsn.bottom(), vsn.end()));
    1.22 +
    1.23 +#define assert_is_available_negative(word_size) \
    1.24 +  assert(!vsn.is_available(word_size), \
    1.25 +    err_msg(#word_size ": " PTR_FORMAT " bytes should not be available in " \
    1.26 +            "VirtualSpaceNode [" PTR_FORMAT ", " PTR_FORMAT ")", \
    1.27 +            (uintptr_t)(word_size * BytesPerWord), vsn.bottom(), vsn.end()));
    1.28 +
    1.29 +  static void test_is_available_positive() {
    1.30 +    // Reserve some memory.
    1.31 +    VirtualSpaceNode vsn(os::vm_allocation_granularity());
    1.32 +    assert(vsn.initialize(), "Failed to setup VirtualSpaceNode");
    1.33 +
    1.34 +    // Commit some memory.
    1.35 +    size_t commit_word_size = os::vm_allocation_granularity() / BytesPerWord;
    1.36 +    bool expanded = vsn.expand_by(commit_word_size, commit_word_size);
    1.37 +    assert(expanded, "Failed to commit");
    1.38 +
    1.39 +    // Check that is_available accepts the committed size.
    1.40 +    assert_is_available_positive(commit_word_size);
    1.41 +
    1.42 +    // Check that is_available accepts half the committed size.
    1.43 +    size_t expand_word_size = commit_word_size / 2;
    1.44 +    assert_is_available_positive(expand_word_size);
    1.45 +  }
    1.46 +
    1.47 +  static void test_is_available_negative() {
    1.48 +    // Reserve some memory.
    1.49 +    VirtualSpaceNode vsn(os::vm_allocation_granularity());
    1.50 +    assert(vsn.initialize(), "Failed to setup VirtualSpaceNode");
    1.51 +
    1.52 +    // Commit some memory.
    1.53 +    size_t commit_word_size = os::vm_allocation_granularity() / BytesPerWord;
    1.54 +    bool expanded = vsn.expand_by(commit_word_size, commit_word_size);
    1.55 +    assert(expanded, "Failed to commit");
    1.56 +
    1.57 +    // Check that is_available doesn't accept a too large size.
    1.58 +    size_t two_times_commit_word_size = commit_word_size * 2;
    1.59 +    assert_is_available_negative(two_times_commit_word_size);
    1.60 +  }
    1.61 +
    1.62 +  static void test_is_available_overflow() {
    1.63 +    // Reserve some memory.
    1.64 +    VirtualSpaceNode vsn(os::vm_allocation_granularity());
    1.65 +    assert(vsn.initialize(), "Failed to setup VirtualSpaceNode");
    1.66 +
    1.67 +    // Commit some memory.
    1.68 +    size_t commit_word_size = os::vm_allocation_granularity() / BytesPerWord;
    1.69 +    bool expanded = vsn.expand_by(commit_word_size, commit_word_size);
    1.70 +    assert(expanded, "Failed to commit");
    1.71 +
    1.72 +    // Calculate a size that will overflow the virtual space size.
    1.73 +    void* virtual_space_max = (void*)(uintptr_t)-1;
    1.74 +    size_t bottom_to_max = pointer_delta(virtual_space_max, vsn.bottom(), 1);
    1.75 +    size_t overflow_size = bottom_to_max + BytesPerWord;
    1.76 +    size_t overflow_word_size = overflow_size / BytesPerWord;
    1.77 +
    1.78 +    // Check that is_available can handle the overflow.
    1.79 +    assert_is_available_negative(overflow_word_size);
    1.80 +  }
    1.81 +
    1.82 +  static void test_is_available() {
    1.83 +    TestVirtualSpaceNodeTest::test_is_available_positive();
    1.84 +    TestVirtualSpaceNodeTest::test_is_available_negative();
    1.85 +    TestVirtualSpaceNodeTest::test_is_available_overflow();
    1.86 +  }
    1.87  };
    1.88  
    1.89  void TestVirtualSpaceNode_test() {
    1.90    TestVirtualSpaceNodeTest::test();
    1.91 +  TestVirtualSpaceNodeTest::test_is_available();
    1.92  }
    1.93  
    1.94  #endif

mercurial