11/*
2- * Copyright (c) 2011, 2018 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2011, 2021 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
3535import java .util .Optional ;
3636import java .util .function .BiConsumer ;
3737
38+ import jdk .test .lib .Platform ;
39+
3840import nsk .share .test .LazyIntArrayToString ;
3941import nsk .share .test .TestUtils ;
4042import vm .mlvm .meth .share .transform .v2 .MHArrayEnvelopeTFPair ;
@@ -68,45 +70,66 @@ public class MHTransformationGen {
6870
6971 private static final boolean USE_THROW_CATCH = false ; // Test bugs
7072
71- private static final Optional <MemoryPoolMXBean > NON_SEGMENTED_CODE_CACHE_POOL ;
72- private static final Optional <MemoryPoolMXBean > NON_NMETHODS_POOL ;
73- private static final Optional <MemoryPoolMXBean > PROFILED_NMETHODS_POOL ;
74- private static final Optional <MemoryPoolMXBean > NON_PROFILED_NMETHODS_POOL ;
75-
76- // Limit numbers are arbitrary, feel free to change if arguably necessary
77- private static final int NON_SEGMENTED_CACHE_ALLOWANCE = 2_000_000 ;
78- private static final int SEGMENTED_CACHE_ALLOWANCE = 1_000_000 ;
79-
80- static {
81- var pools = ManagementFactory .getMemoryPoolMXBeans ();
82- NON_SEGMENTED_CODE_CACHE_POOL = pools .stream ()
83- .filter (pool -> pool .getName ().equals ("CodeCache" )).findFirst ();
84- NON_NMETHODS_POOL = pools .stream ()
85- .filter (pool -> pool .getName ().equals ("CodeHeap 'non-nmethods'" )).findFirst ();
86- PROFILED_NMETHODS_POOL = pools .stream ()
87- .filter (pool -> pool .getName ().equals ("CodeHeap 'profiled nmethods'" )).findFirst ();
88- NON_PROFILED_NMETHODS_POOL = pools .stream ()
89- .filter (pool -> pool .getName ().equals ("CodeHeap 'non-profiled nmethods'" )).findFirst ();
90- }
73+ /**
74+ * The class is used for periodical checks if a code-cache consuming operation
75+ * could be executed (i.e. if code cache has enought free space for a typical operation).
76+ */
77+ private static class CodeCacheMonitor {
78+
79+ private static final Optional <MemoryPoolMXBean > NON_SEGMENTED_CODE_CACHE_POOL ;
80+ private static final Optional <MemoryPoolMXBean > NON_NMETHODS_POOL ;
81+ private static final Optional <MemoryPoolMXBean > PROFILED_NMETHODS_POOL ;
82+ private static final Optional <MemoryPoolMXBean > NON_PROFILED_NMETHODS_POOL ;
83+
84+ // Trial runs show up that maximal increase in code cache consumption between checks (for one
85+ // cycle/tree build in MHTransformationGen::createSequence), falls within the following intervals:
86+ //
87+ // | Threads number | Without Xcomp | With Xcomp |
88+ // |----------------|---------------|------------|
89+ // | 1 | 100-200 K | 400-500 K |
90+ // | 10 | 1 - 2 M | 5-6 M |
91+ //
92+ // Those numbers are approximate (since trees are generated randomly and the total consumption
93+ // between checks depends on how threads are aligned - for example, if all threads finish up their
94+ // cycles approximately at one time, the consumption increase will be the highest, like with a
95+ // resonance's amplitude)
96+ // The 10 threads is chosen as it is a typical number for multi-threaded tests.
97+ //
98+ // Based on these numbers, values of 10 M for Xcomp and 5 M for non-Xcomp, were suggested.
99+ private static final int NON_SEGMENTED_CACHE_ALLOWANCE = Platform .isComp () ? 10_000_000 : 5_000_000 ;
100+ private static final int SEGMENTED_CACHE_ALLOWANCE = Platform .isComp () ? 10_000_000 : 5_000_000 ;
101+
102+ static {
103+ var pools = ManagementFactory .getMemoryPoolMXBeans ();
104+ NON_SEGMENTED_CODE_CACHE_POOL = pools .stream ()
105+ .filter (pool -> pool .getName ().equals ("CodeCache" )).findFirst ();
106+ NON_NMETHODS_POOL = pools .stream ()
107+ .filter (pool -> pool .getName ().equals ("CodeHeap 'non-nmethods'" )).findFirst ();
108+ PROFILED_NMETHODS_POOL = pools .stream ()
109+ .filter (pool -> pool .getName ().equals ("CodeHeap 'profiled nmethods'" )).findFirst ();
110+ NON_PROFILED_NMETHODS_POOL = pools .stream ()
111+ .filter (pool -> pool .getName ().equals ("CodeHeap 'non-profiled nmethods'" )).findFirst ();
112+ }
91113
92- public static class ThrowCatchTestException extends Throwable {
93- private static final long serialVersionUID = -6749961303738648241L ;
94- }
114+ public static final boolean isCodeCacheEffectivelyFull () {
115+ var result = new Object () { boolean value = false ; };
95116
96- private static final boolean isCodeCacheEffectivelyFull () {
97- var result = new Object () { boolean value = false ; };
117+ BiConsumer <MemoryPoolMXBean , Integer > check = (pool , limit ) -> {
118+ var usage = pool .getUsage ();
119+ result .value |= usage .getMax () - usage .getUsed () < limit ;
120+ };
98121
99- BiConsumer < MemoryPoolMXBean , Integer > check = (pool , limit ) -> {
100- var usage = pool . getUsage ( );
101- result . value |= usage . getMax () - usage . getUsed () < limit ;
102- } ;
122+ NON_SEGMENTED_CODE_CACHE_POOL . ifPresent (pool -> check . accept ( pool , NON_SEGMENTED_CACHE_ALLOWANCE ));
123+ NON_NMETHODS_POOL . ifPresent ( pool -> check . accept ( pool , SEGMENTED_CACHE_ALLOWANCE ) );
124+ PROFILED_NMETHODS_POOL . ifPresent ( pool -> check . accept ( pool , SEGMENTED_CACHE_ALLOWANCE )) ;
125+ NON_PROFILED_NMETHODS_POOL . ifPresent ( pool -> check . accept ( pool , SEGMENTED_CACHE_ALLOWANCE )) ;
103126
104- NON_SEGMENTED_CODE_CACHE_POOL .ifPresent (pool -> check .accept (pool , NON_SEGMENTED_CACHE_ALLOWANCE ));
105- NON_NMETHODS_POOL .ifPresent (pool -> check .accept (pool , SEGMENTED_CACHE_ALLOWANCE ));
106- PROFILED_NMETHODS_POOL .ifPresent (pool -> check .accept (pool , SEGMENTED_CACHE_ALLOWANCE ));
107- NON_PROFILED_NMETHODS_POOL .ifPresent (pool -> check .accept (pool , SEGMENTED_CACHE_ALLOWANCE ));
127+ return result .value ;
128+ }
129+ };
108130
109- return result .value ;
131+ public static class ThrowCatchTestException extends Throwable {
132+ private static final long serialVersionUID = -6749961303738648241L ;
110133 }
111134
112135 @ SuppressWarnings ("unused" )
@@ -131,7 +154,7 @@ public static MHMacroTF createSequence(Argument finalRetVal, Object boundObj, Me
131154
132155 final int cyclesToBuild = nextInt (MAX_CYCLES );
133156 for ( int i = 0 ; i < cyclesToBuild ; i ++) {
134- if (isCodeCacheEffectivelyFull ()) {
157+ if (CodeCacheMonitor . isCodeCacheEffectivelyFull ()) {
135158 Env .traceNormal ("Not enought code cache to build up MH sequences anymore. " +
136159 " Has only been able to achieve " + i + " out of " + cyclesToBuild );
137160 break ;
0 commit comments