1 /* 2 * Copyright (c) 2002, 2010, 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 /* 27 */ 28 29 #include "jni.h" 30 #include "jni_util.h" 31 #include "jlong.h" 32 #include <string.h> 33 34 #define MBYTE 1048576 35 36 #define GETCRITICAL_OR_RETURN(bytes, env, obj) { \ 37 bytes = (*env)->GetPrimitiveArrayCritical(env, obj, NULL); \ 38 if (bytes == NULL) { \ 39 if ((*env)->ExceptionOccurred(env) == NULL) \ 40 JNU_ThrowInternalError(env, "Unable to get array"); \ 41 return; \ 42 } \ 43 } 44 45 #define RELEASECRITICAL(bytes, env, obj, mode) { \ 46 (*env)->ReleasePrimitiveArrayCritical(env, obj, bytes, mode); \ 47 } 48 49 #define SWAPSHORT(x) ((jshort)(((x) << 8) | (((x) >> 8) & 0xff))) 50 #define SWAPINT(x) ((jint)((SWAPSHORT((jshort)(x)) << 16) | \ 51 (SWAPSHORT((jshort)((x) >> 16)) & 0xffff))) 52 #define SWAPLONG(x) ((jlong)(((jlong)SWAPINT((jint)(x)) << 32) | \ 53 ((jlong)SWAPINT((jint)((x) >> 32)) & 0xffffffff))) 54 55 /* The destination buffer passed to Java_java_nio_Bits_copyFromShor<type>tArray 56 * function and the source buffer passed to Java_java_nio_Bits_copyTo<type>Array 57 * may not be aligned on <type>'s boundary. Inform the compiler about this via 58 * 'unaligned' attribute, provided it supports this attribute. Fro recent 59 * compilers, use __has_attribute preprocessor predicate; if it is not available, 60 * we know that GCC supports it. 61 */ 62 #ifndef __has_attribute 63 #define __has_attribute(x) 0 64 #endif 65 66 #if defined(__GNUC__) || __has_attribute(aligned) 67 typedef jshort __attribute__((aligned(1))) jshort_unaligned; 68 typedef jint __attribute__((aligned(1))) jint_unaligned; 69 typedef jlong __attribute__((aligned(1))) jlong_unaligned; 70 #else 71 typedef jshort jshort_unaligned; 72 typedef jint jint_unaligned; 73 typedef jlong jlong_unaligned; 74 #endif 75 76 JNIEXPORT void JNICALL 77 Java_java_nio_Bits_copyFromShortArray(JNIEnv *env, jclass clazz, jobject src, 78 jlong srcPos, jlong dstAddr, jlong length) 79 { 80 jbyte *bytes; 81 size_t size; 82 jshort *srcShort, *endShort; 83 jshort_unaligned *dstShort; 84 jshort tmpShort; 85 86 dstShort = (jshort_unaligned *)jlong_to_ptr(dstAddr); 87 88 while (length > 0) { 89 size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; 90 91 GETCRITICAL_OR_RETURN(bytes, env, src); 92 93 srcShort = (jshort *)(bytes + srcPos); 94 endShort = srcShort + (size / sizeof(jshort)); 95 while (srcShort < endShort) { 96 tmpShort = *srcShort++; 97 *dstShort++ = SWAPSHORT(tmpShort); 98 } 99 100 RELEASECRITICAL(bytes, env, src, JNI_ABORT); 101 102 length -= size; 103 srcPos += size; 104 } 105 } 106 107 JNIEXPORT void JNICALL 108 Java_java_nio_Bits_copyToShortArray(JNIEnv *env, jclass clazz, jlong srcAddr, 109 jobject dst, jlong dstPos, jlong length) 110 { 111 jbyte *bytes; 112 size_t size; 113 jshort_unaligned *srcShort, *endShort; 114 jshort *dstShort; 115 jshort tmpShort; 116 117 srcShort = (jshort_unaligned *)jlong_to_ptr(srcAddr); 118 119 while (length > 0) { 120 size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; 121 122 GETCRITICAL_OR_RETURN(bytes, env, dst); 123 124 dstShort = (jshort *)(bytes + dstPos); 125 endShort = srcShort + (size / sizeof(jshort)); 126 while (srcShort < endShort) { 127 tmpShort = *srcShort++; 128 *dstShort++ = SWAPSHORT(tmpShort); 129 } 130 131 RELEASECRITICAL(bytes, env, dst, 0); 132 133 length -= size; 134 dstPos += size; 135 } 136 } 137 138 JNIEXPORT void JNICALL 139 Java_java_nio_Bits_copyFromIntArray(JNIEnv *env, jclass clazz, jobject src, 140 jlong srcPos, jlong dstAddr, jlong length) 141 { 142 jbyte *bytes; 143 size_t size; 144 jint *srcInt, *endInt; 145 jint_unaligned *dstInt; 146 jint tmpInt; 147 148 dstInt = (jint_unaligned *)jlong_to_ptr(dstAddr); 149 150 while (length > 0) { 151 size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; 152 153 GETCRITICAL_OR_RETURN(bytes, env, src); 154 155 srcInt = (jint *)(bytes + srcPos); 156 endInt = srcInt + (size / sizeof(jint)); 157 while (srcInt < endInt) { 158 tmpInt = *srcInt++; 159 *dstInt++ = SWAPINT(tmpInt); 160 } 161 162 RELEASECRITICAL(bytes, env, src, JNI_ABORT); 163 164 length -= size; 165 srcPos += size; 166 } 167 } 168 169 JNIEXPORT void JNICALL 170 Java_java_nio_Bits_copyToIntArray(JNIEnv *env, jclass clazz, jlong srcAddr, 171 jobject dst, jlong dstPos, jlong length) 172 { 173 jbyte *bytes; 174 size_t size; 175 jint_unaligned *srcInt, *endInt; 176 jint *dstInt; 177 jint tmpInt; 178 179 srcInt = (jint_unaligned *)jlong_to_ptr(srcAddr); 180 181 while (length > 0) { 182 size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; 183 184 GETCRITICAL_OR_RETURN(bytes, env, dst); 185 186 dstInt = (jint *)(bytes + dstPos); 187 endInt = srcInt + (size / sizeof(jint)); 188 while (srcInt < endInt) { 189 tmpInt = *srcInt++; 190 *dstInt++ = SWAPINT(tmpInt); 191 } 192 193 RELEASECRITICAL(bytes, env, dst, 0); 194 195 length -= size; 196 dstPos += size; 197 } 198 } 199 200 JNIEXPORT void JNICALL 201 Java_java_nio_Bits_copyFromLongArray(JNIEnv *env, jclass clazz, jobject src, 202 jlong srcPos, jlong dstAddr, jlong length) 203 { 204 jbyte *bytes; 205 size_t size; 206 jlong *srcLong, *endLong; 207 jlong_unaligned *dstLong; 208 jlong tmpLong; 209 210 dstLong = (jlong_unaligned *)jlong_to_ptr(dstAddr); 211 212 while (length > 0) { 213 size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; 214 215 GETCRITICAL_OR_RETURN(bytes, env, src); 216 217 srcLong = (jlong *)(bytes + srcPos); 218 endLong = srcLong + (size / sizeof(jlong)); 219 while (srcLong < endLong) { 220 tmpLong = *srcLong++; 221 *dstLong++ = SWAPLONG(tmpLong); 222 } 223 224 RELEASECRITICAL(bytes, env, src, JNI_ABORT); 225 226 length -= size; 227 srcPos += size; 228 } 229 } 230 231 JNIEXPORT void JNICALL 232 Java_java_nio_Bits_copyToLongArray(JNIEnv *env, jclass clazz, jlong srcAddr, 233 jobject dst, jlong dstPos, jlong length) 234 { 235 jbyte *bytes; 236 size_t size; 237 jlong_unaligned *srcLong, *endLong; 238 jlong *dstLong; 239 jlong tmpLong; 240 241 srcLong = (jlong_unaligned *)jlong_to_ptr(srcAddr); 242 243 while (length > 0) { 244 size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; 245 246 GETCRITICAL_OR_RETURN(bytes, env, dst); 247 248 dstLong = (jlong *)(bytes + dstPos); 249 endLong = srcLong + (size / sizeof(jlong)); 250 while (srcLong < endLong) { 251 tmpLong = *srcLong++; 252 *dstLong++ = SWAPLONG(tmpLong); 253 } 254 255 RELEASECRITICAL(bytes, env, dst, 0); 256 257 length -= size; 258 dstPos += size; 259 } 260 }