/* * Copyright (c) 2012, 2012, 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 com.sun.max.vm.heap.gcx; import com.sun.max.annotate.*; import com.sun.max.memory.*; import com.sun.max.unsafe.*; import com.sun.max.vm.*; import com.sun.max.vm.MaxineVM.Phase; import com.sun.max.vm.heap.HeapScheme.GCRequest; import com.sun.max.vm.log.VMLog.Record; import com.sun.max.vm.log.hosted.*; import com.sun.max.vm.runtime.*; /** * Simple heap sizing policy for a generational heap with a old generation made of two semi-spaces and a non-aging nursery. * * The policy computes the maximum and initial size of the heap based on the maximum and initial heap memory specified via * the <code>-Xmx</code> and <code>-Xms</code> command line arguments. Note that the memory specified via these command line argument * is not the effective heap size, due to the semi-space nature of the heap. The effective heap size is the young generation size plus the size of a single * old generation semi-space. The size of the young generation is computed as a percentage of this effective heap size. * * Resizing decision takes place after every full collection, and operates in two mode: normal and degraded. * During normal mode, the young generation is always sized to the specified maximum percentage of the heap size. * Heap size changes are driven by min/max ratio of free space in the old generation: if free space drops below a minimum threshold, the heap is increased; * if it increases above a max threshold, the heap is shrunk. * * The policy transitions to degraded mode when the old generation is already max-ed up and doesn't have enough space to cover evacuation from the young generation. * The degraded mode operates by reducing the percentage of heap used by the young generation in order to reduce the evacuated amount at minor collections, * and re-distribute this space to the old generation (equally among the semi-space). This is similar to Appel's generational collector. * * An out of memory situation occurs when the minimum size for a young generation is met. */ public final class GenSSHeapSizingPolicy implements GenHeapSizingPolicy { /** * Knob for turning off shrinking of the heap. */ private static boolean DisableHeapShrink = false; /** * Knob for specifying the percentage of heap space used for the young generation. * The percentage is only change when entering degraded mode (wherein the size of the young generation is decreased to give up more space to the old generation). */ private static int YoungGenHeapPercent = 40; static { VMOptions.addFieldOption("-XX:", "DisableHeapShrink", GenSSHeapSizingPolicy.class, "Disable shrinking the heap when true", Phase.PRISTINE); VMOptions.addFieldOption("-XX:", "YoungGenHeapPercent", GenSSHeapSizingPolicy.class, "Percentage of heap size that must be used by young gen", Phase.PRISTINE); } /** * Minimal size of the young generation (5% of the effective heap size). */ static final int MinYoungGenPercent = 5; /** * Absolute lowest bound for the size of a young generation. If MinYoungGenPercent * heap size is lower than this bound, then the bound is used instead. * The lowest bound must be enough to fire a out-of-memory exception. */ static final Size MinYoungGenSize = Size.K.times(128); public static final HeapSizingPolicyLogger logger = new HeapSizingPolicyLogger(); /** * Minimum effective heap size a generational heap can operate with. * @return an effective heap size. */ private static Size minEffectiveHeapSize() { return MinYoungGenSize.times(2); } /** * Log 2 of the size generations are always aligned to. * Generation are always aligned to some power of two, typically a page or a power of two of the page size. */ private int log2Alignment; /** * Size to which generations are aligned to. In other words, <pre>unitSize = Size.fromInt(1).shiftedLeft({@link #log2Alignment})</pre> */ private Size unitSize; /** * Max percentage of free space after GC to avoid shrinking. */ private int maxFreePercent = 70; /** * Min percentage of heap free after GC to increase heap size. Must not be lower than {@link #youngGenMaxHeapPercentage} */ private int minFreePercent = 40; /** * Min change in heap size due to GC. */ private Size minHeapDeltaBytes = Size.K.times(128); private Size minYoungGenDelta; /** * Maximum percentage of effective heap size the young generation can occupy. * Used in normal mode to size the young generation. */ private int youngGenMaxHeapPercentage; private Size initHeapSize; private Size maxHeapSize; /** * Size of the old generation when the heap is at its maximum size. * This is used as a threshold for degraded mode. Past that point, * the policy can only reduce the size of the young generation (by reducing {@link #youngGenHeapPercentage}) * to give more breathing room to the old generation. */ private Size maxHeapOldGenSize; /** * True if in normal mode, false if degraded. */ private boolean normalMode = true; /** * When set to true, disable shrinking the heap. * This flag is automatically set if the vm options specify an initial heap size equal to the max heap size, or if the DisableHeapShrink options is set to true. */ private boolean disableHeapShrink = false; private boolean outOfMemory = false; @INSPECTED private boolean minorEvacuationOverflow = false; @INSPECTED private boolean oldEvacuationOverflow = false; /** * Young generation heap percentage computed by the last resizing request. */ private int youngGenHeapPercentage; /** * Heap size computed by the last resizing request. */ private Size heapSize; private Size alignUp(Size size) { Size alignment = unitSize.minus(1); return size.plus(alignment).and(alignment.not()); } private Size alignDown(Size size) { Size alignment = unitSize.minus(1); return size.and(alignment.not()); } /** * Compute the effective heap size (one semi-space old generation plus the young generation) from total space available and the * percentage of effective heap size the young generation should occupy. * Let OS = old gen semi-space size, YS = young gen size, H = the effective heap size, and YP the percentage of effective heap size * the young generation should occupy (i.e., <code>youngGenHeapPercentage</code>), and M the total heap space provided (i.e., <code>heapSpace</code>). * We have: * (1) H = OS + YS * (2) YS = YP H * (3) M = 2 OS + YS * From these, we can derive H, the effective heap size H = M / ( 2 - YP) * Note that the larger YP, the larger the effective heap size. * However, in practice, YP must not be such that the young generation is larger * than a old generation semi-space, or the worst case evacuation for a minor collection cannot be supported. * * @param heapSpace total space available for a heap * @return the effective heap size */ private Size computeEffectiveHeapSize(Size heapSpace) { return alignUp(heapSpace.times(100).dividedBy(200 - youngGenHeapPercentage)); } private static Size percent(Size size, int percentage) { return size.times(percentage).dividedBy(100); } public Size minYoungGenSize() { Size size = percent(maxHeapSize, MinYoungGenPercent); return alignUp(size.lessThan(MinYoungGenSize) ? MinYoungGenSize : size); } public GenSSHeapSizingPolicy() { } /** * Construct an instance of the sizing policy, parameterized with an alignment constraint for generation size, and an upper bound of young generation size, * wherein the upper bound is specified as a percentage of the effective heap size. * * @param initSize initial amount of memory available to the heap * @param maxSize maximum amount of memory available to the heap * @param log2Alignment alignment constraints that each space of the heap should satisfy. */ public void initialize(Size initSize, Size maxSize, int log2Alignment) { int youngGenMaxHeapPercentage = YoungGenHeapPercent; // Run validation of heap sizing parameters. FatalError.check(youngGenMaxHeapPercentage > 0 && youngGenMaxHeapPercentage < 100, "Not a valid percentage of heap size"); FatalError.check(log2Alignment > 0 && log2Alignment < Word.widthValue().numberOfBits, "Not a valid log2 alignment"); this.youngGenMaxHeapPercentage = youngGenMaxHeapPercentage; this.log2Alignment = log2Alignment; this.unitSize = Size.fromInt(1).shiftedLeft(log2Alignment); this.disableHeapShrink = (initSize == maxSize) || DisableHeapShrink; Size initHS = computeEffectiveHeapSize(initSize); initHeapSize = initHS.lessThan(minEffectiveHeapSize()) ? minEffectiveHeapSize() : initHS; maxHeapSize = computeEffectiveHeapSize(maxSize); minYoungGenDelta = alignUp(percent(maxHeapSize, 1)); if (maxHeapSize.lessThan(minEffectiveHeapSize())) { Log.printToPowerOfTwoUnits(maxSize); Log.print(" not enough space to initialize heap (max heap size ="); Log.printToPowerOfTwoUnits(maxHeapSize); Log.print(")"); MaxineVM.exit(-1); } youngGenHeapPercentage = youngGenMaxHeapPercentage; heapSize = initHeapSize; maxHeapOldGenSize = maxHeapSize.minus(minYoungGenSize()); if (logger.enabled()) { logger.logInitializeHeap(heapSize.toLong(), initialYoungGenSize().toLong(), initialOldGenSize().toLong(), maxHeapSize.toLong(), percent(maxHeapSize, youngGenMaxHeapPercentage).toLong(), maxHeapOldGenSize.toLong()); } } @Override public Size initialYoungGenSize() { Size size = percent(initHeapSize, youngGenMaxHeapPercentage); return alignUp(size.lessThan(MinYoungGenSize) ? MinYoungGenSize : size); } @Override public Size initialOldGenSize() { return initHeapSize.minus(initialYoungGenSize()); } @Override public Size maxYoungGenSize() { return alignUp(percent(maxHeapSize, youngGenMaxHeapPercentage)); } @Override public Size maxOldGenSize() { return maxHeapOldGenSize; } public Size heapSize() { return heapSize; } public Size youngGenSize() { Size size = percent(heapSize, youngGenHeapPercentage); return alignUp(size.lessThan(MinYoungGenSize) ? MinYoungGenSize : size); } public Size oldGenSize() { return heapSize.minus(youngGenSize()); } public boolean shouldPerformFullGC(Size estimatedEvacuation, Size oldGenFreeSpace, boolean oldSpaceMutatorOverflow) { final boolean needsFullGC = minorEvacuationOverflow || oldSpaceMutatorOverflow || estimatedEvacuation.greaterThan(oldGenFreeSpace); if (logger.enabled()) { logger.logShouldPerformFullGC(estimatedEvacuation.toLong(), oldGenFreeSpace.toLong(), minorEvacuationOverflow, oldSpaceMutatorOverflow, needsFullGC); } return needsFullGC; } public void notifyMinorEvacuationOverflow() { minorEvacuationOverflow = true; } public void notifyMinorEvacuationOverflowRange(MemoryRegion overflowArea) { if (logger.enabled()) { logger.logMinorOverflowEvacuation(overflowArea.start(), overflowArea.end()); } } public void notifyFullEvacuationOverflow() { oldEvacuationOverflow = true; } public void notifyFullEvacuationOverflowRange(Address start, Address end) { if (logger.enabled()) { logger.logFullOverflowEvacuation(start, end); } } public void notifyOutOfMemory() { outOfMemory = true; } public boolean minorEvacuationOverflow() { return minorEvacuationOverflow; } public boolean fullEvacuationOverflow() { return oldEvacuationOverflow; } public void clearNotifications() { outOfMemory = false; oldEvacuationOverflow = false; minorEvacuationOverflow = false; } private boolean sizeDownYoungGen(Size estimatedEvacuation, Size oldGenFreeSpace) { Size ys = youngGenSize(); Size minYS = minYoungGenSize(); if (ys.greaterThan(minYS)) { // Reduce nursery size to redistribute space to the old generation. // If the estimated evacuation is larger than half the size of the nursery, we only redistribute half of the young gen to avoid // sharp drop to the young gen size due to a spike in evacuation. Size oldSpaceNeeded = alignUp(estimatedEvacuation.minus(oldGenFreeSpace)); Size maxYoungGenTax = ys.dividedBy(4); if (oldSpaceNeeded.greaterThan(maxYoungGenTax)) { oldSpaceNeeded = maxYoungGenTax; } if (oldSpaceNeeded.lessThan(minYoungGenDelta)) { oldSpaceNeeded = minYoungGenDelta; } Size newYoungGenSize = ys.minus(oldSpaceNeeded.times(2)); if (newYoungGenSize.lessThan(minYS)) { youngGenHeapPercentage = MinYoungGenPercent; heapSize = minYS.plus(maxHeapOldGenSize); } else { // We're taking 2*oldSpaceNeeded off the young generation to redistribute it equally to each of the old gen semi-space. // Consequently, the effective heap size is reduced by 1*oldSpaceNeeded. Size newHeapSize = heapSize.minus(oldSpaceNeeded); int newYoungGenHeapPercentage = newYoungGenSize.times(100).dividedBy(newHeapSize).toInt(); if (!(newYoungGenHeapPercentage >= MinYoungGenPercent && newYoungGenHeapPercentage <= youngGenMaxHeapPercentage)) { Log.print("newYoungGenHeapPercentage = "); Log.println(newYoungGenHeapPercentage); Log.print("newHeapSize = "); Log.printToPowerOfTwoUnits(newHeapSize); Log.print(" ("); Log.print(newHeapSize.toLong()); Log.println(")"); FatalError.unexpected("incorrect downsizing of young gen"); } heapSize = newHeapSize; youngGenHeapPercentage = newYoungGenHeapPercentage; } normalMode = false; if (logger.enabled()) { logger.logChangeYoungPercent(heapSize.toLong(), youngGenSize().toLong(), oldGenSize().toLong(), youngGenHeapPercentage); } return true; } outOfMemory = true; return false; } private void adjustForEstimatedEvacuation(Size estimatedEvacuation, Size usedSpace, Size targetGrowth) { Size newHeapSize = alignUp(usedSpace.plus(estimatedEvacuation).times(100).dividedBy(100 - youngGenHeapPercentage)); FatalError.check(newHeapSize.greaterEqual(heapSize), "new computed heap size must not be smaller than previous heap size"); if (newHeapSize.minus(heapSize).lessThan(minHeapDeltaBytes)) { newHeapSize = heapSize.plus(minHeapDeltaBytes); } if (newHeapSize.greaterThan(maxHeapSize)) { newHeapSize = maxHeapSize; } Size delta = targetGrowth.plus(newHeapSize.minus(heapSize)); // for logging only. heapSize = newHeapSize; if (logger.enabled()) { logger.logGrowHeap(heapSize.toLong(), youngGenSize().toLong(), oldGenSize().toLong(), delta.toLong()); } } public boolean canIncreaseSizeDuringFullGC(Size overflowEvacuationSize, Size oldGenFreeSpace) { FatalError.check(minorEvacuationOverflow, "Shouldn't resizing during full GC without minor evacuation overflow"); return canIncreaseSize(overflowEvacuationSize, oldGenFreeSpace); } private boolean canIncreaseSize(Size oldFreeSpaceNeeded, Size currentOldFreeSpace) { final Size usedSpace = oldGenSize().minus(currentOldFreeSpace); if (normalMode) { Size freeHeapSpace = heapSize.minus(usedSpace); if (heapSize.lessThan(maxHeapSize)) { FatalError.check(normalMode, "Heap sizing policy must be in normal mode"); Size minFreeHeapSpace = percent(heapSize, minFreePercent); if (freeHeapSpace.greaterEqual(minFreeHeapSpace)) { if (currentOldFreeSpace.greaterEqual(oldFreeSpaceNeeded)) { return false; } // We're above the ratio of free space, but that isn't enough to cover the estimated evacuation space. // Recompute the heap size using the estimated evacuation as free old generation space. adjustForEstimatedEvacuation(oldFreeSpaceNeeded, usedSpace, Size.zero()); return true; } minFreeHeapSpace = alignUp(usedSpace.times(minFreePercent).dividedBy(100 - minFreePercent)); final Size targetGrowth = minFreeHeapSpace.minus(freeHeapSpace); heapSize = usedSpace.plus(minFreeHeapSpace); if (oldGenSize().minus(usedSpace).lessThan(oldFreeSpaceNeeded)) { adjustForEstimatedEvacuation(oldFreeSpaceNeeded, usedSpace, targetGrowth); } else if (logger.enabled()) { logger.logGrowHeap(heapSize.toLong(), youngGenSize().toLong(), oldGenSize().toLong(), targetGrowth.toLong()); } return true; } else if (currentOldFreeSpace.lessThan(oldFreeSpaceNeeded)) { return sizeDownYoungGen(oldFreeSpaceNeeded, currentOldFreeSpace); } return false; } if (currentOldFreeSpace.lessThan(oldFreeSpaceNeeded)) { return sizeDownYoungGen(oldFreeSpaceNeeded, currentOldFreeSpace); } return false; } /** * Recompute heap and generation size based on information provided. * The new heap and generation sizes can be consulted using the methods {@link #heapSize()} {@link #youngGenSize()} {@link #oldGenSize()}. * * @param estimatedEvacuation estimation of the amount of bytes that will be evacuated in the next minor collection * @param oldGenFreeSpace free space in the old generation * @param oldGenMutatorOverflow {@code true} if a mutator overflowed the old generation * @param oldSpaceRequestedBytes space requested in the old generation by the current {@link GCRequest}. * @return true if the policy requires changes of generation and heap sizes. */ public boolean resizeAfterFullGC(Size estimatedEvacuation, Size oldGenFreeSpace, boolean oldGenMutatorOverflow, Size oldSpaceRequestedBytes) { minorEvacuationOverflow = false; final Size usedSpace = oldGenSize().minus(oldGenFreeSpace); Size freeHeapSpace = heapSize.minus(usedSpace); Size maxFreeHeapSpace = percent(heapSize, maxFreePercent); // Should we shrink ? // Don't bother if the evacuator ended up out of memory. // Also, for simplicity, we don't if the full GC was trigger because of a mutator overflow, otherwise we risk shrinking below what the mutator was requesting. // Trying to be smarter requires providing here the actual size requested by the mutator. if (!(oldGenMutatorOverflow || outOfMemory) && freeHeapSpace.greaterThan(maxFreeHeapSpace) && maxFreeHeapSpace.greaterEqual(estimatedEvacuation)) { if (normalMode) { if (disableHeapShrink) { return false; } Size newHeapSize = alignUp(usedSpace.plus(maxFreeHeapSpace)); Size delta = newHeapSize.minus(heapSize); heapSize = newHeapSize; if (logger.enabled()) { logger.logShrinkHeap(heapSize.toLong(), youngGenSize().toLong(), oldGenSize().toLong(), delta.toLong()); } return true; } // If degraded mode, do nothing. return false; } // Should we grow ? final Size oldFreeSpaceNeeded = estimatedEvacuation.greaterThan(oldSpaceRequestedBytes) ? estimatedEvacuation : oldSpaceRequestedBytes; return canIncreaseSize(oldFreeSpaceNeeded, oldGenFreeSpace); } public boolean outOfMemory() { return outOfMemory; } /* * Interface for logging heap resizing decisions made by the GenSSHeapSizingPolicy. * The interface uses long instead of Size to improve human-readability from the inspector's log views. */ @HOSTED_ONLY @VMLoggerInterface(defaultConstructor = true) private interface HeapSizingPolicyLoggerInterface { void shouldPerformFullGC( @VMLogParam(name = "estimatedEvacuation") long estimatedEvacuation, @VMLogParam(name = "freeOldSpace") long freeOldSpace, @VMLogParam(name = "minorEvacuationOverflow") boolean minorEvacuationOverflow, @VMLogParam(name = "oldSpaceMutatorOverflow") boolean oldSpaceMutatorOverflow, @VMLogParam(name = "shouldPerformFullGC") boolean shouldPerformFullGC ); void minorOverflowEvacuation( @VMLogParam(name = "start") Address start, @VMLogParam(name = "end") Address end ); void changeYoungPercent( @VMLogParam(name = "heapSize") long heapSize, @VMLogParam(name = "youngSize") long youngSize, @VMLogParam(name = "oldSize") long oldSize, @VMLogParam(name = "youngGenHeapPercentage") int youngGenHeapPercentage ); void growHeap( @VMLogParam(name = "heapSize") long heapSize, @VMLogParam(name = "youngSize") long youngSize, @VMLogParam(name = "oldSize") long oldSize, @VMLogParam(name = "delta") long delta ); void shrinkHeap( @VMLogParam(name = "heapSize") long heapSize, @VMLogParam(name = "youngSize") long youngSize, @VMLogParam(name = "oldSize") long oldSize, @VMLogParam(name = "delta") long delta ); void initializeHeap( @VMLogParam(name = "heapSize") long heapSize, @VMLogParam(name = "youngSize") long youngSize, @VMLogParam(name = "oldSize") long oldSize, @VMLogParam(name = "maxHeapSize") long maxHeapSize, @VMLogParam(name = "maxYoungSize") long maxYoungSize, @VMLogParam(name = "maxOldSize") long maxOldSize ); void fullOverflowEvacuation( @VMLogParam(name = "start") Address start, @VMLogParam(name = "end") Address end ); } static final class HeapSizingPolicyLogger extends HeapSizingPolicyLoggerAuto { HeapSizingPolicyLogger() { super("HeapSizingPolicy", "Heap Resizing after full GC"); } private void traceHeapSize(long heapSize, long youngSize, long oldSize) { Log.print("Heap: size = "); Log.printToPowerOfTwoUnits(Size.fromLong(heapSize)); Log.print(" [ young = "); Log.printToPowerOfTwoUnits(Size.fromLong(youngSize)); Log.print(" + old = "); Log.printToPowerOfTwoUnits(Size.fromLong(oldSize)); Log.println("]"); } @Override protected void traceChangeYoungPercent(long heapSize, long youngSize, long oldSize, int youngGenHeapPercentage) { Log.print("Change young gen heap % = "); Log.println(youngGenHeapPercentage); traceHeapSize(heapSize, youngSize, oldSize); } @Override protected void traceGrowHeap(long heapSize, long youngSize, long oldSize, long delta) { Log.print("Grow heap size +="); Log.printlnToPowerOfTwoUnits(Size.fromLong(delta)); traceHeapSize(heapSize, youngSize, oldSize); } @Override protected void traceShrinkHeap(long heapSize, long youngSize, long oldSize, long delta) { Log.print("Shrink heap size -="); Log.printlnToPowerOfTwoUnits(Size.fromLong(delta)); traceHeapSize(heapSize, youngSize, oldSize); } @Override protected void traceShouldPerformFullGC(long estimatedEvacuation, long freeOldSpace, boolean minorEvacuationOverflow, boolean oldSpaceMutatorOverflow, boolean shouldPerformFullGC) { Log.print("Estimated next evacuation: "); Log.printToPowerOfTwoUnits(Size.fromLong(estimatedEvacuation)); Log.print(", Free old space: "); Log.printToPowerOfTwoUnits(Size.fromLong(freeOldSpace)); Log.print(", minorEvacuationOverflow = "); Log.print(minorEvacuationOverflow); Log.print(", oldSpaceMutatorOverflow = "); Log.print(oldSpaceMutatorOverflow); Log.print(", shouldPerformFullGC = "); Log.println(shouldPerformFullGC); } @Override protected void traceInitializeHeap(long heapSize, long youngSize, long oldSize, long maxHeapSize, long maxYoungSize, long maxOldSize) { Log.print("Initial "); traceHeapSize(heapSize, youngSize, oldSize); Log.print(", Max heap size = "); Log.printToPowerOfTwoUnits(Size.fromLong(maxHeapSize)); Log.print(", Max young size = "); Log.printToPowerOfTwoUnits(Size.fromLong(maxYoungSize)); Log.print(", Max old size = "); Log.printlnToPowerOfTwoUnits(Size.fromLong(maxOldSize)); } @Override protected void traceMinorOverflowEvacuation(Address start, Address end) { Log.print("Minor"); Log.printRange(start, end, true); } @Override protected void traceFullOverflowEvacuation(Address start, Address end) { Log.print("Full"); Log.printRange(start, end, true); } } // START GENERATED CODE private static abstract class HeapSizingPolicyLoggerAuto extends com.sun.max.vm.log.VMLogger { public enum Operation { ChangeYoungPercent, FullOverflowEvacuation, GrowHeap, InitializeHeap, MinorOverflowEvacuation, ShouldPerformFullGC, ShrinkHeap; @SuppressWarnings("hiding") public static final Operation[] VALUES = values(); } private static final int[] REFMAPS = null; protected HeapSizingPolicyLoggerAuto(String name, String optionDescription) { super(name, Operation.VALUES.length, optionDescription, REFMAPS); } protected HeapSizingPolicyLoggerAuto() { } @Override public String operationName(int opCode) { return Operation.VALUES[opCode].name(); } @INLINE public final void logChangeYoungPercent(long heapSize, long youngSize, long oldSize, int youngGenHeapPercentage) { log(Operation.ChangeYoungPercent.ordinal(), longArg(heapSize), longArg(youngSize), longArg(oldSize), intArg(youngGenHeapPercentage)); } protected abstract void traceChangeYoungPercent(long heapSize, long youngSize, long oldSize, int youngGenHeapPercentage); @INLINE public final void logFullOverflowEvacuation(Address start, Address end) { log(Operation.FullOverflowEvacuation.ordinal(), start, end); } protected abstract void traceFullOverflowEvacuation(Address start, Address end); @INLINE public final void logGrowHeap(long heapSize, long youngSize, long oldSize, long delta) { log(Operation.GrowHeap.ordinal(), longArg(heapSize), longArg(youngSize), longArg(oldSize), longArg(delta)); } protected abstract void traceGrowHeap(long heapSize, long youngSize, long oldSize, long delta); @INLINE public final void logInitializeHeap(long heapSize, long youngSize, long oldSize, long maxHeapSize, long maxYoungSize, long maxOldSize) { log(Operation.InitializeHeap.ordinal(), longArg(heapSize), longArg(youngSize), longArg(oldSize), longArg(maxHeapSize), longArg(maxYoungSize), longArg(maxOldSize)); } protected abstract void traceInitializeHeap(long heapSize, long youngSize, long oldSize, long maxHeapSize, long maxYoungSize, long maxOldSize); @INLINE public final void logMinorOverflowEvacuation(Address start, Address end) { log(Operation.MinorOverflowEvacuation.ordinal(), start, end); } protected abstract void traceMinorOverflowEvacuation(Address start, Address end); @INLINE public final void logShouldPerformFullGC(long estimatedEvacuation, long freeOldSpace, boolean minorEvacuationOverflow, boolean oldSpaceMutatorOverflow, boolean shouldPerformFullGC) { log(Operation.ShouldPerformFullGC.ordinal(), longArg(estimatedEvacuation), longArg(freeOldSpace), booleanArg(minorEvacuationOverflow), booleanArg(oldSpaceMutatorOverflow), booleanArg(shouldPerformFullGC)); } protected abstract void traceShouldPerformFullGC(long estimatedEvacuation, long freeOldSpace, boolean minorEvacuationOverflow, boolean oldSpaceMutatorOverflow, boolean shouldPerformFullGC); @INLINE public final void logShrinkHeap(long heapSize, long youngSize, long oldSize, long delta) { log(Operation.ShrinkHeap.ordinal(), longArg(heapSize), longArg(youngSize), longArg(oldSize), longArg(delta)); } protected abstract void traceShrinkHeap(long heapSize, long youngSize, long oldSize, long delta); @Override protected void trace(Record r) { switch (r.getOperation()) { case 0: { //ChangeYoungPercent traceChangeYoungPercent(toLong(r, 1), toLong(r, 2), toLong(r, 3), toInt(r, 4)); break; } case 1: { //FullOverflowEvacuation traceFullOverflowEvacuation(toAddress(r, 1), toAddress(r, 2)); break; } case 2: { //GrowHeap traceGrowHeap(toLong(r, 1), toLong(r, 2), toLong(r, 3), toLong(r, 4)); break; } case 3: { //InitializeHeap traceInitializeHeap(toLong(r, 1), toLong(r, 2), toLong(r, 3), toLong(r, 4), toLong(r, 5), toLong(r, 6)); break; } case 4: { //MinorOverflowEvacuation traceMinorOverflowEvacuation(toAddress(r, 1), toAddress(r, 2)); break; } case 5: { //ShouldPerformFullGC traceShouldPerformFullGC(toLong(r, 1), toLong(r, 2), toBoolean(r, 3), toBoolean(r, 4), toBoolean(r, 5)); break; } case 6: { //ShrinkHeap traceShrinkHeap(toLong(r, 1), toLong(r, 2), toLong(r, 3), toLong(r, 4)); break; } } } } // END GENERATED CODE }