--- old/src/java.base/share/classes/jdk/internal/misc/Unsafe.java 2016-02-09 19:35:21.122284969 -0800 +++ new/src/java.base/share/classes/jdk/internal/misc/Unsafe.java 2016-02-09 19:35:20.938281706 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, 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 @@ -458,6 +458,79 @@ copyMemory(null, srcAddress, null, destAddress, bytes); } + private boolean isPrimitiveArray(Class c) { + Class componentType = c.getComponentType(); + return componentType != null && componentType.isPrimitive(); + } + + private native void copySwapMemory0(Object srcBase, long srcOffset, + Object destBase, long destOffset, + long bytes, long elemSize); + + + /** + * Copies all elements from one block of memory to another block, + * *unconditionally* byte swapping the elements on the fly. + * + *

This method determines each block's base address by means of two parameters, + * and so it provides (in effect) a double-register addressing mode, + * as discussed in {@link #getInt(Object,long)}. When the object reference is null, + * the offset supplies an absolute base address. + * + * @since 9 + */ + public void copySwapMemory(Object srcBase, long srcOffset, + Object destBase, long destOffset, + long bytes, long elemSize) { + if (bytes < 0) { + throw new IllegalArgumentException(); + } + if (elemSize != 2 && elemSize != 4 && elemSize != 8) { + throw new IllegalArgumentException(); + } + if (bytes % elemSize != 0) { + throw new IllegalArgumentException(); + } + if ((srcBase == null && srcOffset == 0) || + (destBase == null && destOffset == 0)) { + throw new NullPointerException(); + } + + // Must be off-heap, or primitive heap arrays + if (srcBase != null && (srcOffset < 0 || !isPrimitiveArray(srcBase.getClass()))) { + throw new IllegalArgumentException(); + } + if (destBase != null && (destOffset < 0 || !isPrimitiveArray(destBase.getClass()))) { + throw new IllegalArgumentException(); + } + + // Sanity check size and offsets on 32-bit platforms. Most + // significant 32 bits must be zero. + if (ADDRESS_SIZE == 4 && + (bytes >>> 32 != 0 || srcOffset >>> 32 != 0 || destOffset >>> 32 != 0)) { + throw new IllegalArgumentException(); + } + + if (bytes == 0) { + return; + } + + copySwapMemory0(srcBase, srcOffset, destBase, destOffset, bytes, elemSize); + } + + /** + * Copies all elements from one block of memory to another block, byte swapping the + * elements on the fly. + * + * This provides a single-register addressing mode, as + * discussed in {@link #getInt(Object,long)}. + * + * Equivalent to {@code copySwapMemory(null, srcAddress, null, destAddress, bytes, elemSize)}. + */ + public void copySwapMemory(long srcAddress, long destAddress, long bytes, long elemSize) { + copySwapMemory(null, srcAddress, null, destAddress, bytes, elemSize); + } + /** * Disposes of a block of native memory, as obtained from {@link * #allocateMemory} or {@link #reallocateMemory}. The address passed to