1/*
2 * Copyright (c) 2014, 2016, 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 * @test AllocationCodeBlobTest
26 * @summary testing of WB::allocate/freeCodeBlob()
27 * @bug 8059624 8064669
28 * @library /test/lib /
29 * @modules java.base/jdk.internal.misc
30 *          java.management
31 * @build sun.hotspot.WhiteBox
32 * @run driver ClassFileInstaller sun.hotspot.WhiteBox
33 *                                sun.hotspot.WhiteBox$WhiteBoxPermission
34 * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
35 *                   -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,null::*
36 *                   -XX:-SegmentedCodeCache
37 *                   compiler.whitebox.AllocationCodeBlobTest
38 * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
39 *                   -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,null::*
40 *                   -XX:+SegmentedCodeCache
41 *                   compiler.whitebox.AllocationCodeBlobTest
42 */
43
44package compiler.whitebox;
45
46import jdk.test.lib.Asserts;
47import jdk.test.lib.InfiniteLoop;
48import sun.hotspot.WhiteBox;
49import sun.hotspot.code.BlobType;
50
51import java.lang.management.MemoryPoolMXBean;
52import java.util.ArrayList;
53import java.util.EnumSet;
54
55public class AllocationCodeBlobTest {
56    private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
57    private static final long CODE_CACHE_SIZE
58            = WHITE_BOX.getUintxVMFlag("ReservedCodeCacheSize");
59    private static final int SIZE = 1;
60
61    public static void main(String[] args) {
62        // check that Sweeper handels dummy blobs correctly
63        Thread t = new Thread(
64                new InfiniteLoop(WHITE_BOX::forceNMethodSweep, 1L),
65                "ForcedSweeper");
66        t.setDaemon(true);
67        System.out.println("Starting " + t.getName());
68        t.start();
69
70        EnumSet<BlobType> blobTypes = BlobType.getAvailable();
71        for (BlobType type : blobTypes) {
72            new AllocationCodeBlobTest(type).test();
73        }
74
75        // check that deoptimization works well w/ dummy blobs
76        t = new Thread(
77                new InfiniteLoop(WHITE_BOX::deoptimizeAll, 1L),
78                "Deoptimize Thread");
79        t.setDaemon(true);
80        System.out.println("Starting " + t.getName());
81        t.start();
82
83        for (int i = 0; i < 10_000; ++i) {
84            for (BlobType type : blobTypes) {
85                long addr = WHITE_BOX.allocateCodeBlob(SIZE, type.id);
86            }
87        }
88
89    }
90
91    private final BlobType type;
92    private final MemoryPoolMXBean bean;
93    private AllocationCodeBlobTest(BlobType type) {
94        this.type = type;
95        bean = type.getMemoryPool();
96    }
97
98    private void test() {
99        System.out.printf("type %s%n", type);
100
101        // Measure the code cache usage after allocate/free.
102        long start = getUsage();
103        long addr1 = WHITE_BOX.allocateCodeBlob(SIZE, type.id);
104        long firstAllocation = getUsage();
105        WHITE_BOX.freeCodeBlob(addr1);
106        long firstFree = getUsage();
107        long addr2 = WHITE_BOX.allocateCodeBlob(SIZE, type.id);
108        long secondAllocation = getUsage();
109        WHITE_BOX.freeCodeBlob(addr2);
110
111        // The following code may trigger resolving of invokedynamic
112        // instructions and therefore method handle intrinsic creation
113        // in the code cache. Make sure this is executed after measuring
114        // the code cache usage.
115        Asserts.assertNE(0, addr1, "first allocation failed");
116        Asserts.assertNE(0, addr2, "second allocation failed");
117        Asserts.assertLTE(start + SIZE, firstAllocation,
118                "allocation should increase memory usage: "
119                + start + " + " + SIZE + " <= " + firstAllocation);
120        Asserts.assertLTE(firstFree, firstAllocation,
121                "free shouldn't increase memory usage: "
122                + firstFree + " <= " + firstAllocation);
123        Asserts.assertEQ(firstAllocation, secondAllocation);
124
125        System.out.println("allocating till possible...");
126        ArrayList<Long> blobs = new ArrayList<>();
127        int size = (int) (CODE_CACHE_SIZE >> 7);
128        while ((addr1 = WHITE_BOX.allocateCodeBlob(size, type.id)) != 0) {
129            blobs.add(addr1);
130        }
131        for (Long blob : blobs) {
132            WHITE_BOX.freeCodeBlob(blob);
133        }
134    }
135
136    private long getUsage() {
137        return bean.getUsage().getUsed();
138    }
139}
140