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  */
  24 
  25 import java.lang.management.MemoryPoolMXBean;
  26 import java.util.EnumSet;
  27 import java.util.ArrayList;
  28 
  29 import sun.hotspot.WhiteBox;
  30 import sun.hotspot.code.BlobType;
  31 import com.oracle.java.testlibrary.Asserts;
  32 
  33 /*
  34  * @test AllocationCodeHeapTest
  35  * @bug 8059624
  36  * @library /testlibrary /testlibrary/whitebox
  37  * @build AllocationCodeHeapTest
  38  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  39  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
  40  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  41  *                   -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,null::*
  42  *                   -XX:-SegmentedCodeCache AllocationCodeHeapTest
  43  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  44  *                   -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,null::*
  45  *                   -XX:+SegmentedCodeCache AllocationCodeHeapTest
  46  * @summary testing of WB::allocate/freeCodeHeap()
  47  */
  48 public class AllocationCodeHeapTest {
  49     private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
  50     private static final long CODE_CACHE_SIZE
  51             = WHITE_BOX.getUintxVMFlag("ReservedCodeCacheSize");
  52     private static final int SIZE = 1;
  53 
  54     public static void main(String[] args) {
  55         // check that Sweeper handels dummy blobs correctly
  56         new ForcedSweeper(500).start();
  57         EnumSet<BlobType> blobTypes = BlobType.getAvailable();
  58         for (BlobType type : blobTypes) {
  59             new AllocationCodeHeapTest(type).test();
  60         }
  61     }
  62 
  63     private final BlobType type;
  64     private final MemoryPoolMXBean bean;
  65     private AllocationCodeHeapTest(BlobType type) {
  66         this.type = type;
  67         bean = type.getMemoryPool();
  68     }
  69 
  70     private void test() {
  71         System.out.printf("type %s%n", type);
  72         long start = getUsage();
  73         long addr = WHITE_BOX.allocateCodeHeap(SIZE, type.id);
  74         long firstAllocation = getUsage();
  75         Asserts.assertLTE(start + SIZE, firstAllocation,
  76                 "allocation should increase memory usage: "
  77                 + start + " + " + SIZE + " <= " + firstAllocation);
  78 
  79         WHITE_BOX.freeCodeHeap(addr);
  80         long firstFree = getUsage();
  81         Asserts.assertLTE(firstFree, firstAllocation,
  82                 "free shouldn't increase memory usage: "
  83                 + firstFree + " <= " + firstAllocation);
  84 
  85         addr = WHITE_BOX.allocateCodeHeap(SIZE, type.id);
  86         long secondAllocation = getUsage();
  87         Asserts.assertEQ(firstAllocation, secondAllocation);
  88 
  89         WHITE_BOX.freeCodeHeap(addr);
  90         System.out.println("allocating till possible...");
  91         ArrayList<Long> blobs = new ArrayList<>();
  92         int size = (int) (CODE_CACHE_SIZE >> 7);
  93         while ((addr = WHITE_BOX.allocateCodeHeap(size, type.id)) != 0) {
  94             blobs.add(addr);
  95         }
  96         for (Long blob : blobs) {
  97             WHITE_BOX.freeCodeHeap(blob);
  98         }
  99     }
 100 
 101     private long getUsage() {
 102         return bean.getUsage().getUsed();
 103     }
 104 
 105     private static class ForcedSweeper extends Thread {
 106         private final int millis;
 107         public ForcedSweeper(int millis) {
 108             super("ForcedSweeper");
 109             setDaemon(true);
 110             this.millis = millis;
 111         }
 112         public void run() {
 113             try {
 114                 while (true) {
 115                     WHITE_BOX.forceNMethodSweep();
 116                     Thread.sleep(millis);
 117                 }
 118             } catch (InterruptedException e) {
 119                 Thread.currentThread().interrupt();
 120                 throw new Error(e);
 121             }
 122         }
 123     }
 124 }