提交 e632514c 编写于 作者: D dbuck

8141491: Unaligned memory access in Bits.c

Summary: Introduce alignment-safe Copy::conjoint_swap and JVM_CopySwapMemory
Reviewed-by: mikael, dholmes
上级 f854a21d
#
# Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 1997, 2018, 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
......@@ -222,12 +222,7 @@ SUNWprivate_1.1 {
Java_java_lang_UNIXProcess_waitForProcessExit;
Java_java_lang_UNIXProcess_forkAndExec;
Java_java_lang_UNIXProcess_destroyProcess;
Java_java_nio_Bits_copyFromShortArray;
Java_java_nio_Bits_copyToShortArray;
Java_java_nio_Bits_copyFromIntArray;
Java_java_nio_Bits_copyToIntArray;
Java_java_nio_Bits_copyFromLongArray;
Java_java_nio_Bits_copyToLongArray;
Java_java_nio_Bits_copySwapMemory0;
Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2;
Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2;
......
/*
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2018, 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
......@@ -835,31 +835,191 @@ class Bits { // package-private
}
}
static void copyFromCharArray(Object src, long srcPos, long dstAddr,
long length)
{
copyFromShortArray(src, srcPos, dstAddr, length);
/**
* Copy and unconditionally byte swap 16 bit elements from a heap array to off-heap memory
*
* @param src
* the source array, must be a 16-bit primitive array type
* @param srcPos
* byte offset within source array of the first element to read
* @param dstAddr
* destination address
* @param length
* number of bytes to copy
*/
static void copyFromCharArray(Object src, long srcPos, long dstAddr, long length) {
copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 2);
}
static void copyToCharArray(long srcAddr, Object dst, long dstPos,
long length)
{
copyToShortArray(srcAddr, dst, dstPos, length);
/**
* Copy and unconditionally byte swap 16 bit elements from off-heap memory to a heap array
*
* @param srcAddr
* source address
* @param dst
* destination array, must be a 16-bit primitive array type
* @param dstPos
* byte offset within the destination array of the first element to write
* @param length
* number of bytes to copy
*/
static void copyToCharArray(long srcAddr, Object dst, long dstPos, long length) {
copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 2);
}
static native void copyFromShortArray(Object src, long srcPos, long dstAddr,
long length);
static native void copyToShortArray(long srcAddr, Object dst, long dstPos,
long length);
/**
* Copy and unconditionally byte swap 16 bit elements from a heap array to off-heap memory
*
* @param src
* the source array, must be a 16-bit primitive array type
* @param srcPos
* byte offset within source array of the first element to read
* @param dstAddr
* destination address
* @param length
* number of bytes to copy
*/
static void copyFromShortArray(Object src, long srcPos, long dstAddr, long length) {
copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 2);
}
static native void copyFromIntArray(Object src, long srcPos, long dstAddr,
long length);
static native void copyToIntArray(long srcAddr, Object dst, long dstPos,
long length);
/**
* Copy and unconditionally byte swap 16 bit elements from off-heap memory to a heap array
*
* @param srcAddr
* source address
* @param dst
* destination array, must be a 16-bit primitive array type
* @param dstPos
* byte offset within the destination array of the first element to write
* @param length
* number of bytes to copy
*/
static void copyToShortArray(long srcAddr, Object dst, long dstPos, long length) {
copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 2);
}
/**
* Copy and unconditionally byte swap 32 bit elements from a heap array to off-heap memory
*
* @param src
* the source array, must be a 32-bit primitive array type
* @param srcPos
* byte offset within source array of the first element to read
* @param dstAddr
* destination address
* @param length
* number of bytes to copy
*/
static void copyFromIntArray(Object src, long srcPos, long dstAddr, long length) {
copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 4);
}
/**
* Copy and unconditionally byte swap 32 bit elements from off-heap memory to a heap array
*
* @param srcAddr
* source address
* @param dst
* destination array, must be a 32-bit primitive array type
* @param dstPos
* byte offset within the destination array of the first element to write
* @param length
* number of bytes to copy
*/
static void copyToIntArray(long srcAddr, Object dst, long dstPos, long length) {
copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 4);
}
static native void copyFromLongArray(Object src, long srcPos, long dstAddr,
long length);
static native void copyToLongArray(long srcAddr, Object dst, long dstPos,
long length);
/**
* Copy and unconditionally byte swap 64 bit elements from a heap array to off-heap memory
*
* @param src
* the source array, must be a 64-bit primitive array type
* @param srcPos
* byte offset within source array of the first element to read
* @param dstAddr
* destination address
* @param length
* number of bytes to copy
*/
static void copyFromLongArray(Object src, long srcPos, long dstAddr, long length) {
copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 8);
}
/**
* Copy and unconditionally byte swap 64 bit elements from off-heap memory to a heap array
*
* @param srcAddr
* source address
* @param dst
* destination array, must be a 64-bit primitive array type
* @param dstPos
* byte offset within the destination array of the first element to write
* @param length
* number of bytes to copy
*/
static void copyToLongArray(long srcAddr, Object dst, long dstPos, long length) {
copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 8);
}
private static boolean isPrimitiveArray(Class<?> c) {
Class<?> componentType = c.getComponentType();
return componentType != null && componentType.isPrimitive();
}
private native static 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.
*
* <p>This method determines each block's base address by means of two parameters,
* and so it provides (in effect) a <em>double-register</em> addressing mode,
* as discussed in {@link sun.misc.Unsafe#getInt(Object,long)}. When the
* object reference is null, the offset supplies an absolute base address.
*
* @since 8u201
*/
private static 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 (unsafe.addressSize() == 4 &&
(bytes >>> 32 != 0 || srcOffset >>> 32 != 0 || destOffset >>> 32 != 0)) {
throw new IllegalArgumentException();
}
if (bytes == 0) {
return;
}
copySwapMemory0(srcBase, srcOffset, destBase, destOffset, bytes, elemSize);
}
}
/*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2018, 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
......@@ -117,6 +117,14 @@ JVM_InitProperties(JNIEnv *env, jobject p);
JNIEXPORT void JNICALL
JVM_OnExit(void (*func)(void));
/*
* java.nio.Bits
*/
JNIEXPORT void JNICALL
JVM_CopySwapMemory(JNIEnv *env, jobject srcObj, jlong srcOffset,
jobject dstObj, jlong dstOffset, jlong size,
jlong elemSize);
/*
* java.lang.Runtime
*/
......
/*
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2018, 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
......@@ -23,259 +23,13 @@
* questions.
*/
/*
*/
#include "jni.h"
#include "jni_util.h"
#include "jlong.h"
#include <string.h>
/*
* WARNING:
*
* Do not replace instances of:
*
* if (length > MBYTE)
* size = MBYTE;
* else
* size = length;
*
* with
*
* size = (length > MBYTE ? MBYTE : length);
*
* This expression causes a c compiler assertion failure when compiling on
* 32-bit sparc.
*/
#define MBYTE 1048576
#define GETCRITICAL_OR_RETURN(bytes, env, obj) { \
bytes = (*env)->GetPrimitiveArrayCritical(env, obj, NULL); \
if (bytes == NULL) { \
if ((*env)->ExceptionOccurred(env) == NULL) \
JNU_ThrowInternalError(env, "Unable to get array"); \
return; \
} \
}
#define RELEASECRITICAL(bytes, env, obj, mode) { \
(*env)->ReleasePrimitiveArrayCritical(env, obj, bytes, mode); \
}
#define SWAPSHORT(x) ((jshort)(((x) << 8) | (((x) >> 8) & 0xff)))
#define SWAPINT(x) ((jint)((SWAPSHORT((jshort)(x)) << 16) | \
(SWAPSHORT((jshort)((x) >> 16)) & 0xffff)))
#define SWAPLONG(x) ((jlong)(((jlong)SWAPINT((jint)(x)) << 32) | \
((jlong)SWAPINT((jint)((x) >> 32)) & 0xffffffff)))
JNIEXPORT void JNICALL
Java_java_nio_Bits_copyFromShortArray(JNIEnv *env, jobject this, jobject src,
jlong srcPos, jlong dstAddr, jlong length)
{
jbyte *bytes;
size_t size;
jshort *srcShort, *dstShort, *endShort;
jshort tmpShort;
dstShort = (jshort *)jlong_to_ptr(dstAddr);
while (length > 0) {
/* do not change this if-else statement, see WARNING above */
if (length > MBYTE)
size = MBYTE;
else
size = (size_t)length;
GETCRITICAL_OR_RETURN(bytes, env, src);
srcShort = (jshort *)(bytes + srcPos);
endShort = srcShort + (size / sizeof(jshort));
while (srcShort < endShort) {
tmpShort = *srcShort++;
*dstShort++ = SWAPSHORT(tmpShort);
}
RELEASECRITICAL(bytes, env, src, JNI_ABORT);
length -= size;
dstAddr += size;
srcPos += size;
}
}
JNIEXPORT void JNICALL
Java_java_nio_Bits_copyToShortArray(JNIEnv *env, jobject this, jlong srcAddr,
jobject dst, jlong dstPos, jlong length)
{
jbyte *bytes;
size_t size;
jshort *srcShort, *dstShort, *endShort;
jshort tmpShort;
srcShort = (jshort *)jlong_to_ptr(srcAddr);
while (length > 0) {
/* do not change this if-else statement, see WARNING above */
if (length > MBYTE)
size = MBYTE;
else
size = (size_t)length;
GETCRITICAL_OR_RETURN(bytes, env, dst);
dstShort = (jshort *)(bytes + dstPos);
endShort = srcShort + (size / sizeof(jshort));
while (srcShort < endShort) {
tmpShort = *srcShort++;
*dstShort++ = SWAPSHORT(tmpShort);
}
RELEASECRITICAL(bytes, env, dst, 0);
length -= size;
srcAddr += size;
dstPos += size;
}
}
JNIEXPORT void JNICALL
Java_java_nio_Bits_copyFromIntArray(JNIEnv *env, jobject this, jobject src,
jlong srcPos, jlong dstAddr, jlong length)
{
jbyte *bytes;
size_t size;
jint *srcInt, *dstInt, *endInt;
jint tmpInt;
dstInt = (jint *)jlong_to_ptr(dstAddr);
while (length > 0) {
/* do not change this code, see WARNING above */
if (length > MBYTE)
size = MBYTE;
else
size = (size_t)length;
GETCRITICAL_OR_RETURN(bytes, env, src);
srcInt = (jint *)(bytes + srcPos);
endInt = srcInt + (size / sizeof(jint));
while (srcInt < endInt) {
tmpInt = *srcInt++;
*dstInt++ = SWAPINT(tmpInt);
}
RELEASECRITICAL(bytes, env, src, JNI_ABORT);
length -= size;
dstAddr += size;
srcPos += size;
}
}
JNIEXPORT void JNICALL
Java_java_nio_Bits_copyToIntArray(JNIEnv *env, jobject this, jlong srcAddr,
jobject dst, jlong dstPos, jlong length)
{
jbyte *bytes;
size_t size;
jint *srcInt, *dstInt, *endInt;
jint tmpInt;
srcInt = (jint *)jlong_to_ptr(srcAddr);
while (length > 0) {
/* do not change this code, see WARNING above */
if (length > MBYTE)
size = MBYTE;
else
size = (size_t)length;
GETCRITICAL_OR_RETURN(bytes, env, dst);
dstInt = (jint *)(bytes + dstPos);
endInt = srcInt + (size / sizeof(jint));
while (srcInt < endInt) {
tmpInt = *srcInt++;
*dstInt++ = SWAPINT(tmpInt);
}
RELEASECRITICAL(bytes, env, dst, 0);
length -= size;
srcAddr += size;
dstPos += size;
}
}
#include "jvm.h"
JNIEXPORT void JNICALL
Java_java_nio_Bits_copyFromLongArray(JNIEnv *env, jobject this, jobject src,
jlong srcPos, jlong dstAddr, jlong length)
{
jbyte *bytes;
size_t size;
jlong *srcLong, *dstLong, *endLong;
jlong tmpLong;
dstLong = (jlong *)jlong_to_ptr(dstAddr);
while (length > 0) {
/* do not change this code, see WARNING above */
if (length > MBYTE)
size = MBYTE;
else
size = (size_t)length;
GETCRITICAL_OR_RETURN(bytes, env, src);
srcLong = (jlong *)(bytes + srcPos);
endLong = srcLong + (size / sizeof(jlong));
while (srcLong < endLong) {
tmpLong = *srcLong++;
*dstLong++ = SWAPLONG(tmpLong);
}
RELEASECRITICAL(bytes, env, src, JNI_ABORT);
length -= size;
dstAddr += size;
srcPos += size;
}
}
JNIEXPORT void JNICALL
Java_java_nio_Bits_copyToLongArray(JNIEnv *env, jobject this, jlong srcAddr,
jobject dst, jlong dstPos, jlong length)
{
jbyte *bytes;
size_t size;
jlong *srcLong, *dstLong, *endLong;
jlong tmpLong;
srcLong = (jlong *)jlong_to_ptr(srcAddr);
while (length > 0) {
/* do not change this code, see WARNING above */
if (length > MBYTE)
size = MBYTE;
else
size = (size_t)length;
GETCRITICAL_OR_RETURN(bytes, env, dst);
dstLong = (jlong *)(bytes + dstPos);
endLong = srcLong + (size / sizeof(jlong));
while (srcLong < endLong) {
tmpLong = *srcLong++;
*dstLong++ = SWAPLONG(tmpLong);
}
RELEASECRITICAL(bytes, env, dst, 0);
length -= size;
srcAddr += size;
dstPos += size;
}
Java_java_nio_Bits_copySwapMemory0(JNIEnv *env, jclass cls, jobject srcObj,
jlong srcOffset, jobject dstObj,
jlong dstOffset, jlong size,
jlong elemSize) {
JVM_CopySwapMemory(env, srcObj, srcOffset, dstObj, dstOffset,
size, elemSize);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册