jdk/src/java.desktop/share/classes/sun/java2d/marlin/ArrayCache.java
changeset 40518 eb9dfc05f8c6
parent 40517 611ca58fca75
parent 40496 7833915c1537
child 40519 e17429a7e843
equal deleted inserted replaced
40517:611ca58fca75 40518:eb9dfc05f8c6
     1 /*
       
     2  * Copyright (c) 2015, 2016, 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 (DO_TRACE) {
       
    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 (DO_TRACE) {
       
    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 (DO_STATS || DO_MONITORS) {
       
    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         // check if needSize is negative or integer overflow:
       
   170         if (needSize < 0) {
       
   171             // hard overflow failure - we can't even accommodate
       
   172             // new items without overflowing
       
   173             throw new ArrayIndexOutOfBoundsException(
       
   174                           "array exceeds maximum capacity !");
       
   175         }
       
   176         assert curSize >= 0;
       
   177         final int initial = (curSize & MASK_CLR_1);
       
   178         int size;
       
   179         if (initial > THRESHOLD_ARRAY_SIZE) {
       
   180             size = initial + (initial >> 1); // x(3/2)
       
   181         } else {
       
   182             size = (initial << 1); // x2
       
   183         }
       
   184         // ensure the new size is >= needed size:
       
   185         if (size < needSize) {
       
   186             // align to 4096 (may overflow):
       
   187             size = ((needSize >> 12) + 1) << 12;
       
   188         }
       
   189         // check integer overflow:
       
   190         if (size < 0) {
       
   191             // resize to maximum capacity:
       
   192             size = Integer.MAX_VALUE;
       
   193         }
       
   194         return size;
       
   195     }
       
   196 
       
   197     /**
       
   198      * Return the new array size (~ x2)
       
   199      * @param curSize current used size
       
   200      * @param needSize needed size
       
   201      * @return new array size
       
   202      */
       
   203     public static long getNewLargeSize(final long curSize, final long needSize) {
       
   204         // check if needSize is negative or integer overflow:
       
   205         if ((needSize >> 31L) != 0L) {
       
   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         assert curSize >= 0L;
       
   212         long size;
       
   213         if (curSize > THRESHOLD_HUGE_ARRAY_SIZE) {
       
   214             size = curSize + (curSize >> 2L); // x(5/4)
       
   215         } else  if (curSize > THRESHOLD_LARGE_ARRAY_SIZE) {
       
   216             size = curSize + (curSize >> 1L); // x(3/2)
       
   217         } else {
       
   218             size = (curSize << 1L); // x2
       
   219         }
       
   220         // ensure the new size is >= needed size:
       
   221         if (size < needSize) {
       
   222             // align to 4096:
       
   223             size = ((needSize >> 12L) + 1L) << 12L;
       
   224         }
       
   225         // check integer overflow:
       
   226         if (size > Integer.MAX_VALUE) {
       
   227             // resize to maximum capacity:
       
   228             size = Integer.MAX_VALUE;
       
   229         }
       
   230         return size;
       
   231     }
       
   232 }