/* * Copyright (c) 2014, 2016, 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. */ package compiler.codecache.jmx; import jdk.test.lib.Asserts; import jdk.test.lib.Utils; import sun.hotspot.WhiteBox; import sun.hotspot.code.BlobType; import sun.hotspot.code.CodeBlob; import javax.management.Notification; import java.lang.management.MemoryPoolMXBean; public final class CodeCacheUtils { /** * Returns the value to be used for code heap allocation */ public static final int ALLOCATION_SIZE = Integer.getInteger("codecache.allocation.size", 100); public static final WhiteBox WB = WhiteBox.getWhiteBox(); public static final long SEGMENT_SIZE = WhiteBox.getWhiteBox().getUintxVMFlag("CodeCacheSegmentSize"); public static final long MIN_BLOCK_LENGTH = WhiteBox.getWhiteBox().getUintxVMFlag("CodeCacheMinBlockLength"); public static final long MIN_ALLOCATION = SEGMENT_SIZE * MIN_BLOCK_LENGTH; private CodeCacheUtils() { // To prevent from instantiation } public static final void hitUsageThreshold(MemoryPoolMXBean bean, BlobType btype) { long initialSize = bean.getUsage().getUsed(); bean.setUsageThreshold(initialSize + 1); long usageThresholdCount = bean.getUsageThresholdCount(); long addr = WB.allocateCodeBlob(1, btype.id); WB.fullGC(); Utils.waitForCondition(() -> bean.getUsageThresholdCount() == usageThresholdCount + 1); WB.freeCodeBlob(addr); } public static final long getHeaderSize(BlobType btype) { long addr = WB.allocateCodeBlob(0, btype.id); int size = CodeBlob.getCodeBlob(addr).size; WB.freeCodeBlob(addr); return size; } public static String getPoolNameFromNotification( Notification notification) { return ((javax.management.openmbean.CompositeDataSupport) notification.getUserData()).get("poolName").toString(); } public static boolean isAvailableCodeHeapPoolName(String name) { return BlobType.getAvailable().stream() .map(BlobType::getMemoryPool) .map(MemoryPoolMXBean::getName) .filter(name::equals) .findAny().isPresent(); } /** * Checks if the usage of the code heap corresponding to 'btype' can be * predicted at runtime if we disable compilation. The usage of the * 'NonNMethod' code heap can not be predicted because we generate adapters * and buffers at runtime. The 'MethodNonProfiled' code heap is also not * predictable because we may generate compiled versions of method handle * intrinsics while resolving methods at runtime. Same applies to 'All'. * * @param btype BlobType to be checked * @return boolean value, true if respective code heap is predictable */ public static boolean isCodeHeapPredictable(BlobType btype) { return btype == BlobType.MethodProfiled; } /** * Verifies that 'newValue' is equal to 'oldValue' if usage of the * corresponding code heap is predictable. Checks the weaker condition * 'newValue >= oldValue' if usage is not predictable because intermediate * allocations may happen. * * @param btype BlobType of the code heap to be checked * @param newValue New value to be verified * @param oldValue Old value to be verified * @param msg Error message if verification fails */ public static void assertEQorGTE(BlobType btype, long newValue, long oldValue, String msg) { if (CodeCacheUtils.isCodeHeapPredictable(btype)) { // Usage is predictable, check strong == condition Asserts.assertEQ(newValue, oldValue, msg); } else { // Usage is not predictable, check weaker >= condition Asserts.assertGTE(newValue, oldValue, msg); } } /** * Verifies that 'newValue' is equal to 'oldValue' if usage of the * corresponding code heap is predictable. Checks the weaker condition * 'newValue <= oldValue' if usage is not predictable because intermediate * allocations may happen. * * @param btype BlobType of the code heap to be checked * @param newValue New value to be verified * @param oldValue Old value to be verified * @param msg Error message if verification fails */ public static void assertEQorLTE(BlobType btype, long newValue, long oldValue, String msg) { if (CodeCacheUtils.isCodeHeapPredictable(btype)) { // Usage is predictable, check strong == condition Asserts.assertEQ(newValue, oldValue, msg); } else { // Usage is not predictable, check weaker <= condition Asserts.assertLTE(newValue, oldValue, msg); } } public static void disableCollectionUsageThresholds() { BlobType.getAvailable().stream() .map(BlobType::getMemoryPool) .filter(MemoryPoolMXBean::isCollectionUsageThresholdSupported) .forEach(b -> b.setCollectionUsageThreshold(0L)); } }