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 #include "JNIHelp.h"
35 
36 /*
37  * WARNING:
38  *
39  * Do not replace instances of:
40  *
41  *   if (length > MBYTE)
42  *     size = MBYTE;
43  *   else
44  *     size = length;
45  *
46  * with
47  *
48  *   size = (length > MBYTE ? MBYTE : length);
49  *
50  * This expression causes a c compiler assertion failure when compiling on
51  * 32-bit sparc.
52  */
53 
54 #define MBYTE 1048576
55 
56 #define GETCRITICAL(bytes, env, obj) { \
57     bytes = (*env)->GetPrimitiveArrayCritical(env, obj, NULL); \
58     if (bytes == NULL) \
59         JNU_ThrowInternalError(env, "Unable to get array"); \
60 }
61 
62 #define RELEASECRITICAL(bytes, env, obj, mode) { \
63     (*env)->ReleasePrimitiveArrayCritical(env, obj, bytes, mode); \
64 }
65 
66 #define SWAPSHORT(x) ((jshort)(((x) << 8) | (((x) >> 8) & 0xff)))
67 #define SWAPINT(x)   ((jint)((SWAPSHORT((jshort)(x)) << 16) | \
68                             (SWAPSHORT((jshort)((x) >> 16)) & 0xffff)))
69 #define SWAPLONG(x)  ((jlong)(((jlong)SWAPINT((jint)(x)) << 32) | \
70                               ((jlong)SWAPINT((jint)((x) >> 32)) & 0xffffffff)))
71 
72 #define NATIVE_METHOD(className, functionName, signature) \
73 { #functionName, signature, (void*)(Java_java_nio_ ## className ## _ ## functionName) }
74 
75 JNIEXPORT void JNICALL
Java_java_nio_Bits_copyFromShortArray(JNIEnv * env,jobject this,jobject src,jlong srcPos,jlong dstAddr,jlong length)76 Java_java_nio_Bits_copyFromShortArray(JNIEnv *env, jobject this, jobject src,
77                                       jlong srcPos, jlong dstAddr, jlong length)
78 {
79     jbyte *bytes;
80     size_t size;
81     jshort *srcShort, *dstShort, *endShort;
82     jshort tmpShort;
83 
84     dstShort = (jshort *)jlong_to_ptr(dstAddr);
85 
86     while (length > 0) {
87         /* do not change this if-else statement, see WARNING above */
88         if (length > MBYTE)
89             size = MBYTE;
90         else
91             size = (size_t)length;
92 
93         GETCRITICAL(bytes, env, src);
94 
95         srcShort = (jshort *)(bytes + srcPos);
96         endShort = srcShort + (size / sizeof(jshort));
97         while (srcShort < endShort) {
98           tmpShort = *srcShort++;
99           *dstShort++ = SWAPSHORT(tmpShort);
100         }
101 
102         RELEASECRITICAL(bytes, env, src, JNI_ABORT);
103 
104         length -= size;
105         dstAddr += size;
106         srcPos += size;
107     }
108 }
109 
110 JNIEXPORT void JNICALL
Java_java_nio_Bits_copyToShortArray(JNIEnv * env,jobject this,jlong srcAddr,jobject dst,jlong dstPos,jlong length)111 Java_java_nio_Bits_copyToShortArray(JNIEnv *env, jobject this, jlong srcAddr,
112                                     jobject dst, jlong dstPos, jlong length)
113 {
114     jbyte *bytes;
115     size_t size;
116     jshort *srcShort, *dstShort, *endShort;
117     jshort tmpShort;
118 
119     srcShort = (jshort *)jlong_to_ptr(srcAddr);
120 
121     while (length > 0) {
122         /* do not change this if-else statement, see WARNING above */
123         if (length > MBYTE)
124             size = MBYTE;
125         else
126             size = (size_t)length;
127 
128         GETCRITICAL(bytes, env, dst);
129 
130         dstShort = (jshort *)(bytes + dstPos);
131         endShort = srcShort + (size / sizeof(jshort));
132         while (srcShort < endShort) {
133             tmpShort = *srcShort++;
134             *dstShort++ = SWAPSHORT(tmpShort);
135         }
136 
137         RELEASECRITICAL(bytes, env, dst, 0);
138 
139         length -= size;
140         srcAddr += size;
141         dstPos += size;
142     }
143 }
144 
145 JNIEXPORT void JNICALL
Java_java_nio_Bits_copyFromIntArray(JNIEnv * env,jobject this,jobject src,jlong srcPos,jlong dstAddr,jlong length)146 Java_java_nio_Bits_copyFromIntArray(JNIEnv *env, jobject this, jobject src,
147                                     jlong srcPos, jlong dstAddr, jlong length)
148 {
149     jbyte *bytes;
150     size_t size;
151     jint *srcInt, *dstInt, *endInt;
152     jint tmpInt;
153 
154     dstInt = (jint *)jlong_to_ptr(dstAddr);
155 
156     while (length > 0) {
157         /* do not change this code, see WARNING above */
158         if (length > MBYTE)
159             size = MBYTE;
160         else
161             size = (size_t)length;
162 
163         GETCRITICAL(bytes, env, src);
164 
165         srcInt = (jint *)(bytes + srcPos);
166         endInt = srcInt + (size / sizeof(jint));
167         while (srcInt < endInt) {
168             tmpInt = *srcInt++;
169             *dstInt++ = SWAPINT(tmpInt);
170         }
171 
172         RELEASECRITICAL(bytes, env, src, JNI_ABORT);
173 
174         length -= size;
175         dstAddr += size;
176         srcPos += size;
177     }
178 }
179 
180 JNIEXPORT void JNICALL
Java_java_nio_Bits_copyToIntArray(JNIEnv * env,jobject this,jlong srcAddr,jobject dst,jlong dstPos,jlong length)181 Java_java_nio_Bits_copyToIntArray(JNIEnv *env, jobject this, jlong srcAddr,
182                                   jobject dst, jlong dstPos, jlong length)
183 {
184     jbyte *bytes;
185     size_t size;
186     jint *srcInt, *dstInt, *endInt;
187     jint tmpInt;
188 
189     srcInt = (jint *)jlong_to_ptr(srcAddr);
190 
191     while (length > 0) {
192         /* do not change this code, see WARNING above */
193         if (length > MBYTE)
194             size = MBYTE;
195         else
196             size = (size_t)length;
197 
198         GETCRITICAL(bytes, env, dst);
199 
200         dstInt = (jint *)(bytes + dstPos);
201         endInt = srcInt + (size / sizeof(jint));
202         while (srcInt < endInt) {
203             tmpInt = *srcInt++;
204             *dstInt++ = SWAPINT(tmpInt);
205         }
206 
207         RELEASECRITICAL(bytes, env, dst, 0);
208 
209         length -= size;
210         srcAddr += size;
211         dstPos += size;
212     }
213 }
214 
215 JNIEXPORT void JNICALL
Java_java_nio_Bits_copyFromLongArray(JNIEnv * env,jobject this,jobject src,jlong srcPos,jlong dstAddr,jlong length)216 Java_java_nio_Bits_copyFromLongArray(JNIEnv *env, jobject this, jobject src,
217                                      jlong srcPos, jlong dstAddr, jlong length)
218 {
219     jbyte *bytes;
220     size_t size;
221     jlong *srcLong, *dstLong, *endLong;
222     jlong tmpLong;
223 
224     dstLong = (jlong *)jlong_to_ptr(dstAddr);
225 
226     while (length > 0) {
227         /* do not change this code, see WARNING above */
228         if (length > MBYTE)
229             size = MBYTE;
230         else
231             size = (size_t)length;
232 
233         GETCRITICAL(bytes, env, src);
234 
235         srcLong = (jlong *)(bytes + srcPos);
236         endLong = srcLong + (size / sizeof(jlong));
237         while (srcLong < endLong) {
238             tmpLong = *srcLong++;
239             *dstLong++ = SWAPLONG(tmpLong);
240         }
241 
242         RELEASECRITICAL(bytes, env, src, JNI_ABORT);
243 
244         length -= size;
245         dstAddr += size;
246         srcPos += size;
247     }
248 }
249 
250 JNIEXPORT void JNICALL
Java_java_nio_Bits_copyToLongArray(JNIEnv * env,jobject this,jlong srcAddr,jobject dst,jlong dstPos,jlong length)251 Java_java_nio_Bits_copyToLongArray(JNIEnv *env, jobject this, jlong srcAddr,
252                                    jobject dst, jlong dstPos, jlong length)
253 {
254     jbyte *bytes;
255     size_t size;
256     jlong *srcLong, *dstLong, *endLong;
257     jlong tmpLong;
258 
259     srcLong = (jlong *)jlong_to_ptr(srcAddr);
260 
261     while (length > 0) {
262         /* do not change this code, see WARNING above */
263         if (length > MBYTE)
264             size = MBYTE;
265         else
266             size = (size_t)length;
267 
268         GETCRITICAL(bytes, env, dst);
269 
270         dstLong = (jlong *)(bytes + dstPos);
271         endLong = srcLong + (size / sizeof(jlong));
272         while (srcLong < endLong) {
273             tmpLong = *srcLong++;
274             *dstLong++ = SWAPLONG(tmpLong);
275         }
276 
277         RELEASECRITICAL(bytes, env, dst, 0);
278 
279         length -= size;
280         srcAddr += size;
281         dstPos += size;
282     }
283 }
284 
285 static JNINativeMethod gMethods[] = {
286     NATIVE_METHOD(Bits, copyFromShortArray, "(Ljava/lang/Object;JJJ)V"),
287     NATIVE_METHOD(Bits, copyToShortArray, "(JLjava/lang/Object;JJ)V"),
288     NATIVE_METHOD(Bits, copyFromIntArray, "(Ljava/lang/Object;JJJ)V"),
289     NATIVE_METHOD(Bits, copyToIntArray, "(JLjava/lang/Object;JJ)V"),
290     NATIVE_METHOD(Bits, copyFromLongArray, "(Ljava/lang/Object;JJJ)V"),
291     NATIVE_METHOD(Bits, copyToLongArray, "(JLjava/lang/Object;JJ)V"),
292 };
293 
register_java_nio_Bits(JNIEnv * env)294 void register_java_nio_Bits(JNIEnv* env) {
295     jniRegisterNativeMethods(env, "java/nio/Bits", gMethods, NELEM(gMethods));
296 }
297