/* * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test OverflowCodeCacheTest * @bug 8059550 8279356 * @summary testing of code cache segments overflow * @library /test/lib * @modules java.base/jdk.internal.misc * java.management * * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,null::* * -XX:-SegmentedCodeCache -Xmixed * compiler.codecache.OverflowCodeCacheTest CompilationDisabled * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,null::* * -XX:+SegmentedCodeCache -Xmixed * compiler.codecache.OverflowCodeCacheTest CompilationDisabled * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:-SegmentedCodeCache -Xmixed * compiler.codecache.OverflowCodeCacheTest */ package compiler.codecache; import jdk.test.lib.Asserts; import jdk.test.whitebox.WhiteBox; import jdk.test.whitebox.code.BlobType; import jdk.test.whitebox.code.CodeBlob; import java.lang.management.MemoryPoolMXBean; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.EnumSet; class Helper { // Uncommon signature to prevent sharing and force creation of a new adapter public void method(float a, float b, float c, Object o) { } } public class OverflowCodeCacheTest { private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); private static boolean COMPILATION_DISABLED = false; public static void main(String[] args) { COMPILATION_DISABLED = args.length > 0; EnumSet blobTypes = BlobType.getAvailable(); for (BlobType type : blobTypes) { new OverflowCodeCacheTest(type).test(); } } private final BlobType type; private final MemoryPoolMXBean bean; private OverflowCodeCacheTest(BlobType type) { this.type = type; this.bean = type.getMemoryPool(); } private void test() { System.out.printf("type %s%n", type); System.out.println("allocating till possible..."); ArrayList blobs = new ArrayList<>(); int compilationActivityMode = -1; // Lock compilation to be able to better control code cache space WHITE_BOX.lockCompilation(); try { long addr; int size = (int) (getHeapSize() >> 7); while ((addr = WHITE_BOX.allocateCodeBlob(size, type.id)) != 0) { blobs.add(addr); BlobType actualType = CodeBlob.getCodeBlob(addr).code_blob_type; if (actualType != type) { // check we got allowed overflow handling Asserts.assertTrue(type.allowTypeWhenOverflow(actualType), type + " doesn't allow using " + actualType + " when overflow"); } } /* now, remember compilationActivityMode to check it later, after freeing, since we possibly have no free cache for further work */ compilationActivityMode = WHITE_BOX.getCompilationActivityMode(); // Use smallest allocation size to make sure all of the available space // is filled up. Don't free these below to put some pressure on the sweeper. while ((addr = WHITE_BOX.allocateCodeBlob(1, type.id)) != 0) { } } finally { try { // Trigger creation of a new adapter for Helper::method // which will fail because we are out of code cache space. Helper helper = new Helper(); } catch (VirtualMachineError e) { // Expected } // Free code cache space for (Long blob : blobs) { WHITE_BOX.freeCodeBlob(blob); } // Let the GC free nmethods and re-enable compilation WHITE_BOX.unlockCompilation(); WHITE_BOX.fullGC(); // Trigger compilation of Helper::method which will hit an assert because // adapter creation failed above due to a lack of code cache space. Helper helper = new Helper(); for (int i = 0; i < 100_000; i++) { helper.method(0, 0, 0, null); } } // Only check this if compilation is disabled, otherwise the sweeper might have // freed enough nmethods to allow for re-enabling compilation. if (COMPILATION_DISABLED) { Asserts.assertNotEquals(compilationActivityMode, 1 /* run_compilation*/, "Compilation must be disabled when CodeCache(CodeHeap) overflows"); } } private long getHeapSize() { return bean.getUsage().getMax(); } }