1 /*
2  * Copyright (c) 2017, 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 package java.nio;
26 
27 import jdk.internal.util.ArraysSupport;
28 
29 /**
30  * Mismatch methods for buffers
31  */
32 final class BufferMismatch {
33 
mismatch(ByteBuffer a, int aOff, ByteBuffer b, int bOff, int length)34     static int mismatch(ByteBuffer a, int aOff, ByteBuffer b, int bOff, int length) {
35         int i = 0;
36         if (length > 7) {
37             if (a.get(aOff) != b.get(bOff))
38                 return 0;
39             i = ArraysSupport.vectorizedMismatch(
40                     a.base(), a.address + aOff,
41                     b.base(), b.address + bOff,
42                     length,
43                     ArraysSupport.LOG2_ARRAY_BYTE_INDEX_SCALE);
44             if (i >= 0) return i;
45             i = length - ~i;
46         }
47         for (; i < length; i++) {
48             if (a.get(aOff + i) != b.get(bOff + i))
49                 return i;
50         }
51         return -1;
52     }
53 
mismatch(CharBuffer a, int aOff, CharBuffer b, int bOff, int length)54     static int mismatch(CharBuffer a, int aOff, CharBuffer b, int bOff, int length) {
55         int i = 0;
56         // Ensure only heap or off-heap buffer instances use the
57         // vectorized mismatch. If either buffer is a StringCharBuffer
58         // (order is null) then the slow path is taken
59         if (length > 3 && a.charRegionOrder() == b.charRegionOrder()
60             && a.charRegionOrder() != null && b.charRegionOrder() != null) {
61             if (a.get(aOff) != b.get(bOff))
62                 return 0;
63             i = ArraysSupport.vectorizedMismatch(
64                     a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_CHAR_INDEX_SCALE),
65                     b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_CHAR_INDEX_SCALE),
66                     length,
67                     ArraysSupport.LOG2_ARRAY_CHAR_INDEX_SCALE);
68             if (i >= 0) return i;
69             i = length - ~i;
70         }
71         for (; i < length; i++) {
72             if (a.get(aOff + i) != b.get(bOff + i))
73                 return i;
74         }
75         return -1;
76     }
77 
mismatch(ShortBuffer a, int aOff, ShortBuffer b, int bOff, int length)78     static int mismatch(ShortBuffer a, int aOff, ShortBuffer b, int bOff, int length) {
79         int i = 0;
80         if (length > 3 && a.order() == b.order()) {
81             if (a.get(aOff) != b.get(bOff))
82                 return 0;
83             i = ArraysSupport.vectorizedMismatch(
84                     a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_SHORT_INDEX_SCALE),
85                     b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_SHORT_INDEX_SCALE),
86                     length,
87                     ArraysSupport.LOG2_ARRAY_SHORT_INDEX_SCALE);
88             if (i >= 0) return i;
89             i = length - ~i;
90         }
91         for (; i < length; i++) {
92             if (a.get(aOff + i) != b.get(bOff + i))
93                 return i;
94         }
95         return -1;
96     }
97 
mismatch(IntBuffer a, int aOff, IntBuffer b, int bOff, int length)98     static int mismatch(IntBuffer a, int aOff, IntBuffer b, int bOff, int length) {
99         int i = 0;
100         if (length > 1 && a.order() == b.order()) {
101             if (a.get(aOff) != b.get(bOff))
102                 return 0;
103             i = ArraysSupport.vectorizedMismatch(
104                     a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_INT_INDEX_SCALE),
105                     b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_INT_INDEX_SCALE),
106                     length,
107                     ArraysSupport.LOG2_ARRAY_INT_INDEX_SCALE);
108             if (i >= 0) return i;
109             i = length - ~i;
110         }
111         for (; i < length; i++) {
112             if (a.get(aOff + i) != b.get(bOff + i))
113                 return i;
114         }
115         return -1;
116     }
117 
mismatch(FloatBuffer a, int aOff, FloatBuffer b, int bOff, int length)118     static int mismatch(FloatBuffer a, int aOff, FloatBuffer b, int bOff, int length) {
119         int i = 0;
120         if (length > 1 && a.order() == b.order()) {
121             if (Float.floatToRawIntBits(a.get(aOff)) == Float.floatToRawIntBits(b.get(bOff))) {
122                 i = ArraysSupport.vectorizedMismatch(
123                         a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_FLOAT_INDEX_SCALE),
124                         b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_FLOAT_INDEX_SCALE),
125                         length,
126                         ArraysSupport.LOG2_ARRAY_FLOAT_INDEX_SCALE);
127             }
128             // Mismatched
129             if (i >= 0) {
130                 // Check if mismatch is not associated with two NaN values; and
131                 // is not associated with +0 and -0
132                 float av = a.get(aOff + i);
133                 float bv = b.get(bOff + i);
134                 if (av != bv && (!Float.isNaN(av) || !Float.isNaN(bv)))
135                     return i;
136 
137                 // Fall back to slow mechanism
138                 // ISSUE: Consider looping over vectorizedMismatch adjusting ranges
139                 // However, requires that returned value be relative to input ranges
140                 i++;
141             }
142             // Matched
143             else {
144                 i = length - ~i;
145             }
146         }
147         for (; i < length; i++) {
148             float av = a.get(aOff + i);
149             float bv = b.get(bOff + i);
150             if (av != bv && (!Float.isNaN(av) || !Float.isNaN(bv)))
151                 return i;
152         }
153         return -1;
154     }
155 
mismatch(LongBuffer a, int aOff, LongBuffer b, int bOff, int length)156     static int mismatch(LongBuffer a, int aOff, LongBuffer b, int bOff, int length) {
157         int i = 0;
158         if (length > 0 && a.order() == b.order()) {
159             if (a.get(aOff) != b.get(bOff))
160                 return 0;
161             i = ArraysSupport.vectorizedMismatch(
162                     a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_LONG_INDEX_SCALE),
163                     b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_LONG_INDEX_SCALE),
164                     length,
165                     ArraysSupport.LOG2_ARRAY_LONG_INDEX_SCALE);
166             return i >= 0 ? i : -1;
167         }
168         for (; i < length; i++) {
169             if (a.get(aOff + i) != b.get(bOff + i))
170                 return i;
171         }
172         return -1;
173     }
174 
mismatch(DoubleBuffer a, int aOff, DoubleBuffer b, int bOff, int length)175     static int mismatch(DoubleBuffer a, int aOff, DoubleBuffer b, int bOff, int length) {
176         int i = 0;
177         if (length > 0 && a.order() == b.order()) {
178             if (Double.doubleToRawLongBits(a.get(aOff)) == Double.doubleToRawLongBits(b.get(bOff))) {
179                 i = ArraysSupport.vectorizedMismatch(
180                         a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_DOUBLE_INDEX_SCALE),
181                         b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_DOUBLE_INDEX_SCALE),
182                         length,
183                         ArraysSupport.LOG2_ARRAY_DOUBLE_INDEX_SCALE);
184             }
185             // Mismatched
186             if (i >= 0) {
187                 // Check if mismatch is not associated with two NaN values; and
188                 // is not associated with +0 and -0
189                 double av = a.get(aOff + i);
190                 double bv = b.get(bOff + i);
191                 if (av != bv && (!Double.isNaN(av) || !Double.isNaN(bv)))
192                     return i;
193 
194                 // Fall back to slow mechanism
195                 // ISSUE: Consider looping over vectorizedMismatch adjusting ranges
196                 // However, requires that returned value be relative to input ranges
197                 i++;
198             }
199             // Matched
200             else {
201                 return -1;
202             }
203         }
204         for (; i < length; i++) {
205             double av = a.get(aOff + i);
206             double bv = b.get(bOff + i);
207             if (av != bv && (!Double.isNaN(av) || !Double.isNaN(bv)))
208                 return i;
209         }
210         return -1;
211     }
212 }
213