1 /* 2 * Copyright (c) 2015, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.java2d.marlin; 27 28 import java.util.Arrays; 29 import static sun.java2d.marlin.MarlinUtils.logInfo; 30 31 public final class ArrayCache implements MarlinConst { 32 33 static final int BUCKETS = 4; 34 static final int MIN_ARRAY_SIZE = 4096; 35 static final int MAX_ARRAY_SIZE; 36 static final int MASK_CLR_1 = ~1; 37 // threshold to grow arrays only by (3/2) instead of 2 38 static final int THRESHOLD_ARRAY_SIZE; 39 static final int[] ARRAY_SIZES = new int[BUCKETS]; 40 // dirty byte array sizes 41 static final int MIN_DIRTY_BYTE_ARRAY_SIZE = 32 * 2048; // 32px x 2048px 42 static final int MAX_DIRTY_BYTE_ARRAY_SIZE; 43 static final int[] DIRTY_BYTE_ARRAY_SIZES = new int[BUCKETS]; 44 // large array thresholds: 45 static final long THRESHOLD_LARGE_ARRAY_SIZE; 46 static final long THRESHOLD_HUGE_ARRAY_SIZE; 47 // stats 48 private static int resizeInt = 0; 49 private static int resizeDirtyInt = 0; 50 private static int resizeDirtyFloat = 0; 51 private static int resizeDirtyByte = 0; 52 private static int oversize = 0; 53 54 static { 55 // initialize buckets for int/float arrays 56 int arraySize = MIN_ARRAY_SIZE; 57 58 for (int i = 0; i < BUCKETS; i++, arraySize <<= 2) { 59 ARRAY_SIZES[i] = arraySize; 60 61 if (doTrace) { 62 logInfo("arraySize[" + i + "]: " + arraySize); 63 } 64 } 65 MAX_ARRAY_SIZE = arraySize >> 2; 66 67 /* initialize buckets for dirty byte arrays 68 (large AA chunk = 32 x 2048 pixels) */ 69 arraySize = MIN_DIRTY_BYTE_ARRAY_SIZE; 70 71 for (int i = 0; i < BUCKETS; i++, arraySize <<= 1) { 72 DIRTY_BYTE_ARRAY_SIZES[i] = arraySize; 73 74 if (doTrace) { 75 logInfo("dirty arraySize[" + i + "]: " + arraySize); 76 } 77 } 78 MAX_DIRTY_BYTE_ARRAY_SIZE = arraySize >> 1; 79 80 // threshold to grow arrays only by (3/2) instead of 2 81 THRESHOLD_ARRAY_SIZE = Math.max(2 * 1024 * 1024, MAX_ARRAY_SIZE); // 2M 82 83 THRESHOLD_LARGE_ARRAY_SIZE = 8L * THRESHOLD_ARRAY_SIZE; // 16M 84 THRESHOLD_HUGE_ARRAY_SIZE = 8L * THRESHOLD_LARGE_ARRAY_SIZE; // 128M 85 86 if (doStats || doMonitors) { 87 logInfo("ArrayCache.BUCKETS = " + BUCKETS); 88 logInfo("ArrayCache.MIN_ARRAY_SIZE = " + MIN_ARRAY_SIZE); 89 logInfo("ArrayCache.MAX_ARRAY_SIZE = " + MAX_ARRAY_SIZE); 90 logInfo("ArrayCache.ARRAY_SIZES = " 91 + Arrays.toString(ARRAY_SIZES)); 92 logInfo("ArrayCache.MIN_DIRTY_BYTE_ARRAY_SIZE = " 93 + MIN_DIRTY_BYTE_ARRAY_SIZE); 94 logInfo("ArrayCache.MAX_DIRTY_BYTE_ARRAY_SIZE = " 95 + MAX_DIRTY_BYTE_ARRAY_SIZE); 96 logInfo("ArrayCache.ARRAY_SIZES = " 97 + Arrays.toString(DIRTY_BYTE_ARRAY_SIZES)); 98 logInfo("ArrayCache.THRESHOLD_ARRAY_SIZE = " 99 + THRESHOLD_ARRAY_SIZE); 100 logInfo("ArrayCache.THRESHOLD_LARGE_ARRAY_SIZE = " 101 + THRESHOLD_LARGE_ARRAY_SIZE); 102 logInfo("ArrayCache.THRESHOLD_HUGE_ARRAY_SIZE = " 103 + THRESHOLD_HUGE_ARRAY_SIZE); 104 } 105 } 106 107 private ArrayCache() { 108 // Utility class 109 } 110 111 static synchronized void incResizeInt() { 112 resizeInt++; 113 } 114 115 static synchronized void incResizeDirtyInt() { 116 resizeDirtyInt++; 117 } 118 119 static synchronized void incResizeDirtyFloat() { 120 resizeDirtyFloat++; 121 } 122 123 static synchronized void incResizeDirtyByte() { 124 resizeDirtyByte++; 125 } 126 127 static synchronized void incOversize() { 128 oversize++; 129 } 130 131 static void dumpStats() { 132 if (resizeInt != 0 || resizeDirtyInt != 0 || resizeDirtyFloat != 0 133 || resizeDirtyByte != 0 || oversize != 0) { 134 logInfo("ArrayCache: int resize: " + resizeInt 135 + " - dirty int resize: " + resizeDirtyInt 136 + " - dirty float resize: " + resizeDirtyFloat 137 + " - dirty byte resize: " + resizeDirtyByte 138 + " - oversize: " + oversize); 139 } 140 } 141 142 // small methods used a lot (to be inlined / optimized by hotspot) 143 144 static int getBucket(final int length) { 145 for (int i = 0; i < ARRAY_SIZES.length; i++) { 146 if (length <= ARRAY_SIZES[i]) { 147 return i; 148 } 149 } 150 return -1; 151 } 152 153 static int getBucketDirtyBytes(final int length) { 154 for (int i = 0; i < DIRTY_BYTE_ARRAY_SIZES.length; i++) { 155 if (length <= DIRTY_BYTE_ARRAY_SIZES[i]) { 156 return i; 157 } 158 } 159 return -1; 160 } 161 162 /** 163 * Return the new array size (~ x2) 164 * @param curSize current used size 165 * @param needSize needed size 166 * @return new array size 167 */ 168 public static int getNewSize(final int curSize, final int needSize) { 169 final int initial = (curSize & MASK_CLR_1); 170 int size; 171 if (initial > THRESHOLD_ARRAY_SIZE) { 172 size = initial + (initial >> 1); // x(3/2) 173 } else { 174 size = (initial) << 1; // x2 175 } 176 // ensure the new size is >= needed size: 177 if (size < needSize) { 178 // align to 4096: 179 size = ((needSize >> 12) + 1) << 12; 180 } 181 return size; 182 } 183 184 /** 185 * Return the new array size (~ x2) 186 * @param curSize current used size 187 * @param needSize needed size 188 * @return new array size 189 */ 190 public static long getNewLargeSize(final long curSize, final long needSize) { 191 long size; 192 if (curSize > THRESHOLD_HUGE_ARRAY_SIZE) { 193 size = curSize + (curSize >> 2L); // x(5/4) 194 } else if (curSize > THRESHOLD_LARGE_ARRAY_SIZE) { 195 size = curSize + (curSize >> 1L); // x(3/2) 196 } else { 197 size = curSize << 1L; // x2 198 } 199 // ensure the new size is >= needed size: 200 if (size < needSize) { 201 // align to 4096: 202 size = ((needSize >> 12) + 1) << 12; 203 } 204 if (size >= Integer.MAX_VALUE) { 205 if (curSize >= Integer.MAX_VALUE) { 206 // hard overflow failure - we can't even accommodate 207 // new items without overflowing 208 throw new ArrayIndexOutOfBoundsException( 209 "array exceeds maximum capacity !"); 210 } 211 // resize to maximum capacity: 212 size = Integer.MAX_VALUE; 213 } 214 return size; 215 } 216 }