1 /* 2 * Copyright (c) 1996, 2013, 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 java.util.zip; 27 28 import sun.nio.ch.DirectBuffer; 29 import java.lang.reflect.Field; 30 import java.nio.ByteBuffer; 31 import java.util.concurrent.RecursiveTask; 32 import java.util.concurrent.ForkJoinPool; 33 import sun.misc.Unsafe; 34 35 /** 36 * A class that can be used to compute the CRC-32 of a data stream. 37 * 38 * <p> Passing a {@code null} argument to a method in this class will cause 39 * a {@link NullPointerException} to be thrown. 40 * 41 * @see Checksum 42 * @author David Connelly 43 */ 44 public 45 class CRC32 implements Checksum { 46 private int crc; 47 48 /** 49 * Creates a new CRC32 object. 50 */ 51 public CRC32() { 52 } 53 54 55 /** 56 * Updates the CRC-32 checksum with the specified byte (the low 57 * eight bits of the argument b). 58 * 59 * @param b the byte to update the checksum with 60 */ 61 public void update(int b) { 62 int c = ~ crc; 63 b = timesXtoThe32[(b ^ c) & 0xFF]; 64 b = b ^ (c >>> 8); 65 crc = ~b; 66 } 67 68 /** 69 * Updates the CRC-32 checksum with the specified array of bytes. 70 */ 71 public void update(byte[] b, int off, int len) { 72 if (b == null) { 73 throw new NullPointerException(); 74 } 75 if (off < 0 || len < 0 || off > b.length - len) { 76 throw new ArrayIndexOutOfBoundsException(); 77 } 78 79 if (len < javaCRCIfSmallerThan) { 80 crc = updateBytesSimple(crc, b, off, len); 81 } else { 82 crc = updateBytesFJ(crc, b, off, len); 83 } 84 } 85 86 /** 87 * Updates the CRC-32 checksum with the specified array of bytes. 88 * 89 * @param b the array of bytes to update the checksum with 90 */ 91 public void update(byte[] b) { 92 crc = updateBytesFJ(crc, b, 0, b.length); 93 } 94 95 /** 96 * Updates the checksum with the bytes from the specified buffer. 97 * 98 * The checksum is updated using 99 * buffer.{@link java.nio.Buffer#remaining() remaining()} 100 * bytes starting at 101 * buffer.{@link java.nio.Buffer#position() position()} 102 * Upon return, the buffer's position will 103 * be updated to its limit; its limit will not have been changed. 104 * 105 * @param buffer the ByteBuffer to update the checksum with 106 * @since 1.8 107 */ 108 public void update(ByteBuffer buffer) { 109 int pos = buffer.position(); 110 int limit = buffer.limit(); 111 assert (pos <= limit); 112 int rem = limit - pos; 113 if (rem <= 0) 114 return; 115 if (buffer instanceof DirectBuffer) { 116 crc = updateByteBufferFJ(crc, ((DirectBuffer)buffer).address(), pos, rem); 117 } else if (buffer.hasArray()) { 118 crc = updateBytesFJ(crc, buffer.array(), pos + buffer.arrayOffset(), rem); 119 } else { 120 byte[] b = new byte[rem]; 121 buffer.get(b); 122 crc = updateBytesFJ(crc, b, 0, b.length); 123 } 124 buffer.position(limit); 125 } 126 127 /** 128 * Resets CRC-32 to initial value. 129 */ 130 public void reset() { 131 crc = 0; 132 } 133 134 /** 135 * Returns CRC-32 value. 136 */ 137 public long getValue() { 138 return (long)crc & 0xffffffffL; 139 } 140 141 private native static int update(int crc, int b); 142 private native static int updateBytes(int crc, byte[] b, int off, int len); 143 144 private native static int updateByteBuffer(int adler, long addr, 145 int off, int len); 146 147 148 private static int updateBytesSimple(int crc, byte[] b, int off, int len) { 149 int[] a = timesXtoThe32; 150 if (a.length < 256) 151 throw new ArrayIndexOutOfBoundsException(); 152 int c = ~crc; 153 for (int i = 0; i < len; i++ ) { 154 int x0 = b[i + off]; 155 x0 = a[(x0 ^ c) & 0xFF]; 156 c = x0 ^ (c >>> 8); 157 } 158 return ~c; 159 } 160 161 private native static boolean init(int[] timesXtoThe32, boolean try_use_clmul); 162 163 /** 164 * timesXtoThe32[a] = rep(poly(a)*x**32) 165 */ 166 static int[] timesXtoThe32; 167 168 /** 169 * powersByLog[i] = rep(x**(2**i)) 170 */ 171 static final int[] powersByLog = new int[32]; 172 173 static final int LOG_PB8_LEN = 8; 174 175 /** 176 * powersBy8[i] = rep(x**(8*i)) 177 */ 178 static final int[] powersBy8 = new int[1 << LOG_PB8_LEN]; 179 180 static final int X_to_the_1 = 0x40000000; 181 static final int X_to_the_0 = 0x80000000; 182 183 /** 184 * Indicates if the clmul instruction is enabled in the native 185 * code; this changes the estimated cost of computing a CRC. 186 */ 187 private static boolean clmulEnabled; 188 189 /** 190 * Helpful for deciding whether to use workstealing or not. 191 */ 192 private static int fjParallelism = ForkJoinPool.getCommonPoolParallelism(); 193 194 /** 195 * Estimated task size below which the fork-join overhead could be too large. 196 * May be modified depending on platform properties. 197 */ 198 static int serialIfSmallerThan = 512 * 1024; 199 200 /** 201 * Estimated CRC size below which the JNI overhead is too large. 202 * May be modified depending on platform properties. 203 */ 204 static int javaCRCIfSmallerThan = 80; 205 206 static int ARRAY_BYTE_BASE_OFFSET = 0; 207 208 static boolean debug = false; 209 210 static { 211 timesXtoThe32 = new int[256]; 212 boolean try_use_clmul = 213 "true".equals(sun.misc.VM.getSavedProperty("sun.zip.clmulSupported")); 214 clmulEnabled = init(timesXtoThe32, try_use_clmul); 215 216 if (clmulEnabled) 217 serialIfSmallerThan *= 2; 218 219 if ("true".equals(sun.misc.VM.getSavedProperty("sun.zip.serialOnly"))) 220 fjParallelism = 1; 221 222 powersByLog[0] = X_to_the_1; 223 for (int i = 1; i < powersByLog.length; i++) { 224 int x = powersByLog[i-1]; 225 powersByLog[i] = mul(x,x); 226 } 227 228 powersBy8[0] = X_to_the_0; 229 for (int i = 1; i < powersBy8.length; i++) { 230 int x = powersBy8[i-1]; 231 powersBy8[i] = mul(x,powersByLog[3]); 232 } 233 234 /* Attempt to do all fork-join splits so that they land on a 16-byte boundary. 235 Even if arrays are only 8-byte aligned, this improves our chances. */ 236 try { 237 Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe"); 238 field.setAccessible(true); 239 Unsafe u = (Unsafe) field.get(null); 240 ARRAY_BYTE_BASE_OFFSET = u.ARRAY_BYTE_BASE_OFFSET; 241 } catch (NoSuchFieldException | SecurityException | 242 IllegalArgumentException | IllegalAccessException e) { 243 // It was just an optimization, no need to fail hard. 244 } 245 } 246 247 /* Java implementation of enough GF arithmetic to combine two CRCs for fork/join. */ 248 249 /** 250 * Performs a carryless 32x32 into 63 (NOT 64) bit multiply. 251 * Note that the low-order term of the polynomial lands in bit 252 * 62, not 63. 253 * 254 * The Intel pclmulqdq instruction works in much the same way, 255 * except that it is 64 x 64 into 128. 256 */ 257 private static long clmul32x32(int a, int b) { 258 long accum = 0; 259 long la = (long) a & 0xffffffffL; 260 long lb = (long) b & 0xffffffffL; 261 while (la != 0) { 262 if (0 != (la & 1)) 263 accum ^= lb; 264 la = la >>> 1; 265 lb = lb << 1; 266 } 267 return accum; 268 } 269 270 /** 271 * Converts a 64-bit polynomial into a 32-bit polynomial, modulo P. 272 */ 273 static int reduceLongTable(long x) { 274 x = (x >>> 8) ^ (timesXtoThe32[(int)(x & 0xFF)] & 0xffffffffL); 275 x = (x >>> 8) ^ (timesXtoThe32[(int)(x & 0xFF)] & 0xffffffffL); 276 x = (x >>> 8) ^ (timesXtoThe32[(int)(x & 0xFF)] & 0xffffffffL); 277 x = (x >>> 8) ^ (timesXtoThe32[(int)(x & 0xFF)] & 0xffffffffL); 278 return (int) x; 279 } 280 281 /** 282 * Returns polynomial a times b modulo P. 283 * The least (x**0) term of the polynomial is 284 * aligned with the sign bit of the returned int. 285 * 286 * @param a 287 * @param b 288 * @return 289 */ 290 static int mul(int a, int b) { 291 long product = clmul32x32(a, b); 292 return reduceLongTable(product << 1); 293 } 294 295 /** 296 * Returns the polynomial for a * x ** 8n, where a 297 * is some other polynomial. n is typically a byte count, 298 * and 8n is the number of bits in n bytes. 299 */ 300 static int timesXtoThe8NTable(int a, int n) { 301 if (n == 0) 302 return a; 303 if (n < powersBy8.length) { 304 return mul(a,powersBy8[n]); 305 } 306 int lo = powersBy8.length - 1; 307 int accum = mul(a,powersBy8[n & lo]); 308 n = n >>> LOG_PB8_LEN; 309 int i = LOG_PB8_LEN + 3; 310 while (n != 0) { 311 if (0 != (n & 1)) 312 accum = mul(accum,powersByLog[i]); 313 n = n >>> 1; 314 i++; 315 } 316 return accum; 317 } 318 319 static int combine(int prev, int next, int next_length) { 320 // x**(8 * length) * prev + next 321 return next ^ timesXtoThe8NTable(prev, next_length); 322 } 323 324 private static int updateBytesFJ(int crc, byte[] b, int off, int len) { 325 if (fjParallelism < 2 || len < serialIfSmallerThan) 326 return updateBytes(crc, b, off, len); 327 CRCArrayTask cat = new CRCArrayTask(crc, b, off, len); 328 cat.invoke(); 329 return cat.join(); 330 } 331 332 private static int updateByteBufferFJ(int crc, long addr, 333 int off, int len) { 334 if (fjParallelism < 2 || len < serialIfSmallerThan) 335 return updateByteBuffer(crc, addr, off, len); 336 CRCBufferTask cat = new CRCBufferTask(crc, addr, off, len); 337 cat.invoke(); 338 return cat.join(); 339 } 340 341 static final class CRCArrayTask extends RecursiveTask<Integer> { 342 final byte[] ba; 343 final int start; 344 final int length; 345 final int crc; 346 347 CRCArrayTask(int crc, byte[] ba, int start, int length) { 348 this.crc = crc; 349 this.ba = ba; 350 this.start = start; 351 this.length = length; 352 } 353 354 @Override 355 protected Integer compute() { 356 if (length < serialIfSmallerThan) { 357 if (length < javaCRCIfSmallerThan) { 358 return updateBytesSimple(crc, ba, start, length); 359 } else { 360 return updateBytes(crc, ba, start, length); 361 } 362 } else { 363 int half = length/2; 364 /* Avoid gratuitous misalignment. */ 365 long addr = ARRAY_BYTE_BASE_OFFSET; // Best we can do given limited info. 366 int unaligned = (int) (addr + start + half) & 15; 367 if (half - unaligned >= 32) 368 half -= unaligned; 369 CRCArrayTask task2 = new CRCArrayTask(0, ba, start + half, length - half); 370 task2.fork(); 371 CRCArrayTask task1 = new CRCArrayTask(crc, ba, start, half); 372 int result1 = task1.compute(); 373 return combine(result1, task2.join(), length - half); 374 } 375 } 376 } 377 378 static final class CRCBufferTask extends RecursiveTask<Integer> { 379 final long addr; 380 final int start; 381 final int length; 382 final int crc; 383 384 CRCBufferTask(int crc, long addr, int start, int length) { 385 this.crc = crc; 386 this.addr = addr; 387 this.start = start; 388 this.length = length; 389 } 390 391 @Override 392 protected Integer compute() { 393 if (length < serialIfSmallerThan) { 394 return updateByteBuffer(crc, addr, start, length); 395 } else { 396 int half = length/2; 397 /* Avoid gratuitous misalignment. */ 398 int unaligned = (int) (addr + start + half) & 15; 399 if (half - unaligned >= 32) 400 half -= unaligned; 401 CRCBufferTask task2 = new CRCBufferTask(0, addr, start + half, length - half); 402 task2.fork(); 403 CRCBufferTask task1 = new CRCBufferTask(crc, addr, start, half); 404 int result1 = task1.compute(); 405 return combine(result1, task2.join(), length - half); 406 } 407 } 408 } 409 }