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 }