src/share/vm/gc_implementation/g1/bufferingOopClosure.cpp

Fri, 10 Oct 2014 15:51:58 +0200

author
tschatzl
date
Fri, 10 Oct 2014 15:51:58 +0200
changeset 7257
e7d0505c8a30
parent 6969
02e61cf08ab3
permissions
-rw-r--r--

8059758: Footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: jwilhelm, brutisso

     1 /*
     2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #include "precompiled.hpp"
    26 #include "gc_implementation/g1/bufferingOopClosure.hpp"
    27 #include "memory/iterator.hpp"
    28 #include "utilities/debug.hpp"
    30 /////////////// Unit tests ///////////////
    32 #ifndef PRODUCT
    34 class TestBufferingOopClosure {
    36   // Helper class to fake a set of oop*s and narrowOop*s.
    37   class FakeRoots {
    38    public:
    39     // Used for sanity checking of the values passed to the do_oops functions in the test.
    40     static const uintptr_t NarrowOopMarker = uintptr_t(1) << (BitsPerWord -1);
    42     int    _num_narrow;
    43     int    _num_full;
    44     void** _narrow;
    45     void** _full;
    47     FakeRoots(int num_narrow, int num_full) :
    48         _num_narrow(num_narrow),
    49         _num_full(num_full),
    50         _narrow((void**)::malloc(sizeof(void*) * num_narrow)),
    51         _full((void**)::malloc(sizeof(void*) * num_full)) {
    53       for (int i = 0; i < num_narrow; i++) {
    54         _narrow[i] = (void*)(NarrowOopMarker + (uintptr_t)i);
    55       }
    56       for (int i = 0; i < num_full; i++) {
    57         _full[i] = (void*)(uintptr_t)i;
    58       }
    59     }
    61     ~FakeRoots() {
    62       ::free(_narrow);
    63       ::free(_full);
    64     }
    66     void oops_do_narrow_then_full(OopClosure* cl) {
    67       for (int i = 0; i < _num_narrow; i++) {
    68         cl->do_oop((narrowOop*)_narrow[i]);
    69       }
    70       for (int i = 0; i < _num_full; i++) {
    71         cl->do_oop((oop*)_full[i]);
    72       }
    73     }
    75     void oops_do_full_then_narrow(OopClosure* cl) {
    76       for (int i = 0; i < _num_full; i++) {
    77         cl->do_oop((oop*)_full[i]);
    78       }
    79       for (int i = 0; i < _num_narrow; i++) {
    80         cl->do_oop((narrowOop*)_narrow[i]);
    81       }
    82     }
    84     void oops_do_mixed(OopClosure* cl) {
    85       int i;
    86       for (i = 0; i < _num_full && i < _num_narrow; i++) {
    87         cl->do_oop((oop*)_full[i]);
    88         cl->do_oop((narrowOop*)_narrow[i]);
    89       }
    90       for (int j = i; j < _num_full; j++) {
    91         cl->do_oop((oop*)_full[i]);
    92       }
    93       for (int j = i; j < _num_narrow; j++) {
    94         cl->do_oop((narrowOop*)_narrow[i]);
    95       }
    96     }
    98     static const int MaxOrder = 2;
   100     void oops_do(OopClosure* cl, int do_oop_order) {
   101       switch(do_oop_order) {
   102         case 0:
   103           oops_do_narrow_then_full(cl);
   104           break;
   105         case 1:
   106           oops_do_full_then_narrow(cl);
   107           break;
   108         case 2:
   109           oops_do_mixed(cl);
   110           break;
   111         default:
   112           oops_do_narrow_then_full(cl);
   113           break;
   114       }
   115     }
   116   };
   118   class CountOopClosure : public OopClosure {
   119     int _narrow_oop_count;
   120     int _full_oop_count;
   121    public:
   122     CountOopClosure() : _narrow_oop_count(0), _full_oop_count(0) {}
   123     void do_oop(narrowOop* p) {
   124       assert((uintptr_t(p) & FakeRoots::NarrowOopMarker) != 0,
   125           "The narrowOop was unexpectedly not marked with the NarrowOopMarker");
   126       _narrow_oop_count++;
   127     }
   129     void do_oop(oop* p){
   130       assert((uintptr_t(p) & FakeRoots::NarrowOopMarker) == 0,
   131           "The oop was unexpectedly marked with the NarrowOopMarker");
   132       _full_oop_count++;
   133     }
   135     int narrow_oop_count() { return _narrow_oop_count; }
   136     int full_oop_count()   { return _full_oop_count; }
   137     int all_oop_count()    { return _narrow_oop_count + _full_oop_count; }
   138   };
   140   class DoNothingOopClosure : public OopClosure {
   141    public:
   142     void do_oop(narrowOop* p) {}
   143     void do_oop(oop* p)       {}
   144   };
   146   static void testCount(int num_narrow, int num_full, int do_oop_order) {
   147     FakeRoots fr(num_narrow, num_full);
   149     CountOopClosure coc;
   150     BufferingOopClosure boc(&coc);
   152     fr.oops_do(&boc, do_oop_order);
   154     boc.done();
   156     #define assert_testCount(got, expected)                                     \
   157        assert((got) == (expected),                                              \
   158            err_msg("Expected: %d, got: %d, when running testCount(%d, %d, %d)", \
   159                (got), (expected), num_narrow, num_full, do_oop_order))
   161     assert_testCount(num_narrow, coc.narrow_oop_count());
   162     assert_testCount(num_full, coc.full_oop_count());
   163     assert_testCount(num_narrow + num_full, coc.all_oop_count());
   164   }
   166   static void testCount() {
   167     int buffer_length = BufferingOopClosure::BufferLength;
   169     for (int order = 0; order < FakeRoots::MaxOrder; order++) {
   170       testCount(0,                 0,                 order);
   171       testCount(10,                0,                 order);
   172       testCount(0,                 10,                order);
   173       testCount(10,                10,                order);
   174       testCount(buffer_length,     10,                order);
   175       testCount(10,                buffer_length,     order);
   176       testCount(buffer_length,     buffer_length,     order);
   177       testCount(buffer_length + 1, 10,                order);
   178       testCount(10,                buffer_length + 1, order);
   179       testCount(buffer_length + 1, buffer_length,     order);
   180       testCount(buffer_length,     buffer_length + 1, order);
   181       testCount(buffer_length + 1, buffer_length + 1, order);
   182     }
   183   }
   185   static void testIsBufferEmptyOrFull(int num_narrow, int num_full, bool expect_empty, bool expect_full) {
   186     FakeRoots fr(num_narrow, num_full);
   188     DoNothingOopClosure cl;
   189     BufferingOopClosure boc(&cl);
   191     fr.oops_do(&boc, 0);
   193     #define assert_testIsBufferEmptyOrFull(got, expected)                             \
   194         assert((got) == (expected),                                                   \
   195             err_msg("Expected: %d, got: %d. testIsBufferEmptyOrFull(%d, %d, %s, %s)", \
   196                 (got), (expected), num_narrow, num_full,                              \
   197                 BOOL_TO_STR(expect_empty), BOOL_TO_STR(expect_full)))
   199     assert_testIsBufferEmptyOrFull(expect_empty, boc.is_buffer_empty());
   200     assert_testIsBufferEmptyOrFull(expect_full, boc.is_buffer_full());
   201   }
   203   static void testIsBufferEmptyOrFull() {
   204     int bl = BufferingOopClosure::BufferLength;
   206     testIsBufferEmptyOrFull(0,       0, true,  false);
   207     testIsBufferEmptyOrFull(1,       0, false, false);
   208     testIsBufferEmptyOrFull(0,       1, false, false);
   209     testIsBufferEmptyOrFull(1,       1, false, false);
   210     testIsBufferEmptyOrFull(10,      0, false, false);
   211     testIsBufferEmptyOrFull(0,      10, false, false);
   212     testIsBufferEmptyOrFull(10,     10, false, false);
   213     testIsBufferEmptyOrFull(0,      bl, false, true);
   214     testIsBufferEmptyOrFull(bl,      0, false, true);
   215     testIsBufferEmptyOrFull(bl/2, bl/2, false, true);
   216     testIsBufferEmptyOrFull(bl-1,    1, false, true);
   217     testIsBufferEmptyOrFull(1,    bl-1, false, true);
   218     // Processed
   219     testIsBufferEmptyOrFull(bl+1,    0, false, false);
   220     testIsBufferEmptyOrFull(bl*2,    0, false, true);
   221   }
   223   static void testEmptyAfterDone(int num_narrow, int num_full) {
   224     FakeRoots fr(num_narrow, num_full);
   226     DoNothingOopClosure cl;
   227     BufferingOopClosure boc(&cl);
   229     fr.oops_do(&boc, 0);
   231     // Make sure all get processed.
   232     boc.done();
   234     assert(boc.is_buffer_empty(),
   235         err_msg("Should be empty after call to done(). testEmptyAfterDone(%d, %d)",
   236             num_narrow, num_full));
   237   }
   239   static void testEmptyAfterDone() {
   240     int bl = BufferingOopClosure::BufferLength;
   242     testEmptyAfterDone(0,       0);
   243     testEmptyAfterDone(1,       0);
   244     testEmptyAfterDone(0,       1);
   245     testEmptyAfterDone(1,       1);
   246     testEmptyAfterDone(10,      0);
   247     testEmptyAfterDone(0,      10);
   248     testEmptyAfterDone(10,     10);
   249     testEmptyAfterDone(0,      bl);
   250     testEmptyAfterDone(bl,      0);
   251     testEmptyAfterDone(bl/2, bl/2);
   252     testEmptyAfterDone(bl-1,    1);
   253     testEmptyAfterDone(1,    bl-1);
   254     // Processed
   255     testEmptyAfterDone(bl+1,    0);
   256     testEmptyAfterDone(bl*2,    0);
   257   }
   259   public:
   260   static void test() {
   261     testCount();
   262     testIsBufferEmptyOrFull();
   263     testEmptyAfterDone();
   264   }
   265 };
   267 void TestBufferingOopClosure_test() {
   268   TestBufferingOopClosure::test();
   269 }
   271 #endif

mercurial