1 /* 2 * Copyright (c) 2013, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 6896617 27 * @summary Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() with SSE instructions on x86 28 * @run main/othervm/timeout=1200 -Xbatch -Xmx256m Test6896617 29 * 30 */ 31 32 import java.util.*; 33 import java.nio.*; 34 import java.nio.charset.*; 35 36 public class Test6896617 { 37 final static int SIZE = 256; 38 39 public static void main(String[] args) { 40 String csn = "ISO-8859-1"; 41 Charset cs = Charset.forName(csn); 42 CharsetEncoder enc = cs.newEncoder(); 43 enc.onMalformedInput(CodingErrorAction.REPLACE) 44 .onUnmappableCharacter(CodingErrorAction.REPLACE); 45 CharsetDecoder dec = cs.newDecoder(); 46 dec.onMalformedInput(CodingErrorAction.REPLACE) 47 .onUnmappableCharacter(CodingErrorAction.REPLACE); 48 49 byte repl = (byte)'?'; 50 enc.replaceWith(new byte[] { repl }); 51 52 // Use internal API for tests. 53 sun.nio.cs.ArrayEncoder arrenc = (sun.nio.cs.ArrayEncoder)enc; 54 sun.nio.cs.ArrayDecoder arrdec = (sun.nio.cs.ArrayDecoder)dec; 55 56 // Populate char[] with chars which can be encoded by ISO_8859_1 (<= 0xFF) 57 Random rnd = new Random(0); 58 int maxchar = 0xFF; 59 char[] a = new char[SIZE]; 60 byte[] b = new byte[SIZE]; 61 char[] at = new char[SIZE]; 62 byte[] bt = new byte[SIZE]; 63 for (int i = 0; i < SIZE; i++) { 64 char c = (char) rnd.nextInt(maxchar); 65 if (!enc.canEncode(c)) { 66 System.out.printf("Something wrong: can't encode c=%03x\n", (int)c); 67 System.exit(97); 68 } 69 a[i] = c; 70 b[i] = (byte)c; 71 at[i] = (char)-1; 72 bt[i] = (byte)-1; 73 } 74 if (arrenc.encode(a, 0, SIZE, bt) != SIZE || !Arrays.equals(b, bt)) { 75 System.out.println("Something wrong: ArrayEncoder.encode failed"); 76 System.exit(97); 77 } 78 if (arrdec.decode(b, 0, SIZE, at) != SIZE || !Arrays.equals(a, at)) { 79 System.out.println("Something wrong: ArrayDecoder.decode failed"); 80 System.exit(97); 81 } 82 for (int i = 0; i < SIZE; i++) { 83 at[i] = (char)-1; 84 bt[i] = (byte)-1; 85 } 86 87 ByteBuffer bb = ByteBuffer.wrap(b); 88 CharBuffer ba = CharBuffer.wrap(a); 89 ByteBuffer bbt = ByteBuffer.wrap(bt); 90 CharBuffer bat = CharBuffer.wrap(at); 91 if (!enc.encode(ba, bbt, true).isUnderflow() || !Arrays.equals(b, bt)) { 92 System.out.println("Something wrong: Encoder.encode failed"); 93 System.exit(97); 94 } 95 if (!dec.decode(bb, bat, true).isUnderflow() || !Arrays.equals(a, at)) { 96 System.out.println("Something wrong: Decoder.decode failed"); 97 System.exit(97); 98 } 99 for (int i = 0; i < SIZE; i++) { 100 at[i] = (char)-1; 101 bt[i] = (byte)-1; 102 } 103 104 // Warm up 105 boolean failed = false; 106 int result = 0; 107 for (int i = 0; i < 10000; i++) { 108 result += arrenc.encode(a, 0, SIZE, bt); 109 result -= arrdec.decode(b, 0, SIZE, at); 110 } 111 for (int i = 0; i < 10000; i++) { 112 result += arrenc.encode(a, 0, SIZE, bt); 113 result -= arrdec.decode(b, 0, SIZE, at); 114 } 115 for (int i = 0; i < 10000; i++) { 116 result += arrenc.encode(a, 0, SIZE, bt); 117 result -= arrdec.decode(b, 0, SIZE, at); 118 } 119 if (result != 0 || !Arrays.equals(b, bt) || !Arrays.equals(a, at)) { 120 failed = true; 121 System.out.println("Failed: ArrayEncoder.encode char[" + SIZE + "] and ArrayDecoder.decode byte[" + SIZE + "]"); 122 } 123 for (int i = 0; i < SIZE; i++) { 124 at[i] = (char)-1; 125 bt[i] = (byte)-1; 126 } 127 128 boolean is_underflow = true; 129 for (int i = 0; i < 10000; i++) { 130 ba.clear(); bb.clear(); bat.clear(); bbt.clear(); 131 boolean enc_res = enc.encode(ba, bbt, true).isUnderflow(); 132 boolean dec_res = dec.decode(bb, bat, true).isUnderflow(); 133 is_underflow = is_underflow && enc_res && dec_res; 134 } 135 for (int i = 0; i < SIZE; i++) { 136 at[i] = (char)-1; 137 bt[i] = (byte)-1; 138 } 139 for (int i = 0; i < 10000; i++) { 140 ba.clear(); bb.clear(); bat.clear(); bbt.clear(); 141 boolean enc_res = enc.encode(ba, bbt, true).isUnderflow(); 142 boolean dec_res = dec.decode(bb, bat, true).isUnderflow(); 143 is_underflow = is_underflow && enc_res && dec_res; 144 } 145 for (int i = 0; i < SIZE; i++) { 146 at[i] = (char)-1; 147 bt[i] = (byte)-1; 148 } 149 for (int i = 0; i < 10000; i++) { 150 ba.clear(); bb.clear(); bat.clear(); bbt.clear(); 151 boolean enc_res = enc.encode(ba, bbt, true).isUnderflow(); 152 boolean dec_res = dec.decode(bb, bat, true).isUnderflow(); 153 is_underflow = is_underflow && enc_res && dec_res; 154 } 155 if (!is_underflow || !Arrays.equals(b, bt) || !Arrays.equals(a, at)) { 156 failed = true; 157 System.out.println("Failed: Encoder.encode char[" + SIZE + "] and Decoder.decode byte[" + SIZE + "]"); 158 } 159 160 // Test encoder with different source and destination sizes 161 System.out.println("Testing different source and destination sizes"); 162 for (int i = 1; i <= SIZE; i++) { 163 for (int j = 1; j <= SIZE; j++) { 164 bt = new byte[j]; 165 // very source's SIZE 166 result = arrenc.encode(a, 0, i, bt); 167 int l = Math.min(i, j); 168 if (result != l) { 169 failed = true; 170 System.out.println("Failed: encode char[" + i + "] to byte[" + j + "]: result = " + result + ", expected " + l); 171 } 172 for (int k = 0; k < l; k++) { 173 if (bt[k] != b[k]) { 174 failed = true; 175 System.out.println("Failed: encoded byte[" + k + "] (" + bt[k] + ") != " + b[k]); 176 } 177 } 178 // very source's offset 179 int sz = SIZE - i + 1; 180 result = arrenc.encode(a, i-1, sz, bt); 181 l = Math.min(sz, j); 182 if (result != l) { 183 failed = true; 184 System.out.println("Failed: encode char[" + sz + "] to byte[" + j + "]: result = " + result + ", expected " + l); 185 } 186 for (int k = 0; k < l; k++) { 187 if (bt[k] != b[i+k-1]) { 188 failed = true; 189 System.out.println("Failed: encoded byte[" + k + "] (" + bt[k] + ") != " + b[i+k-1]); 190 } 191 } 192 } 193 } 194 195 // Test encoder with char > 0xFF 196 System.out.println("Testing big char"); 197 198 byte orig = (byte)'A'; 199 bt = new byte[SIZE]; 200 for (int i = 1; i <= SIZE; i++) { 201 for (int j = 0; j < i; j++) { 202 a[j] += 0x100; 203 // make sure to replace a different byte 204 bt[j] = orig; 205 result = arrenc.encode(a, 0, i, bt); 206 if (result != i) { 207 failed = true; 208 System.out.println("Failed: encode char[" + i + "] to byte[" + i + "]: result = " + result + ", expected " + i); 209 } 210 if (bt[j] != repl) { 211 failed = true; 212 System.out.println("Failed: encoded replace byte[" + j + "] (" + bt[j] + ") != " + repl); 213 } 214 bt[j] = b[j]; // Restore to compare whole array 215 for (int k = 0; k < i; k++) { 216 if (bt[k] != b[k]) { 217 failed = true; 218 System.out.println("Failed: encoded byte[" + k + "] (" + bt[k] + ") != " + b[k]); 219 } 220 } 221 a[j] -= 0x100; // Restore 222 } 223 } 224 225 // Test sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() performance. 226 227 int itrs = Integer.getInteger("iterations", 1000000); 228 int size = Integer.getInteger("size", 256); 229 a = new char[size]; 230 b = new byte[size]; 231 bt = new byte[size]; 232 for (int i = 0; i < size; i++) { 233 char c = (char) rnd.nextInt(maxchar); 234 if (!enc.canEncode(c)) { 235 System.out.printf("Something wrong: can't encode c=%03x\n", (int)c); 236 System.exit(97); 237 } 238 a[i] = c; 239 b[i] = (byte)-1; 240 bt[i] = (byte)c; 241 } 242 ba = CharBuffer.wrap(a); 243 bb = ByteBuffer.wrap(b); 244 boolean enc_res = enc.encode(ba, bb, true).isUnderflow(); 245 if (!enc_res || !Arrays.equals(b, bt)) { 246 failed = true; 247 System.out.println("Failed 1: Encoder.encode char[" + size + "]"); 248 } 249 for (int i = 0; i < size; i++) { 250 b[i] = (byte)-1; 251 } 252 253 // Make sure to recompile method if needed before performance run. 254 for (int i = 0; i < 10000; i++) { 255 ba.clear(); bb.clear(); 256 enc_res = enc_res && enc.encode(ba, bb, true).isUnderflow(); 257 } 258 for (int i = 0; i < size; i++) { 259 b[i] = (byte)-1; 260 } 261 for (int i = 0; i < 10000; i++) { 262 ba.clear(); bb.clear(); 263 enc_res = enc_res && enc.encode(ba, bb, true).isUnderflow(); 264 } 265 if (!enc_res || !Arrays.equals(b, bt)) { 266 failed = true; 267 System.out.println("Failed 2: Encoder.encode char[" + size + "]"); 268 } 269 for (int i = 0; i < size; i++) { 270 b[i] = (byte)-1; 271 } 272 273 System.out.println("Testing ISO_8859_1$Encode.encodeArrayLoop() performance"); 274 long start = System.currentTimeMillis(); 275 for (int i = 0; i < itrs; i++) { 276 ba.clear(); bb.clear(); 277 enc_res = enc_res && enc.encode(ba, bb, true).isUnderflow(); 278 } 279 long end = System.currentTimeMillis(); 280 if (!enc_res || !Arrays.equals(b, bt)) { 281 failed = true; 282 System.out.println("Failed 3: Encoder.encode char[" + size + "]"); 283 } else { 284 System.out.println("size: " + size + " time: " + (end - start)); 285 } 286 287 // Test sun.nio.cs.ISO_8859_1$Encode.encode() performance. 288 289 // Make sure to recompile method if needed before performance run. 290 result = 0; 291 for (int i = 0; i < size; i++) { 292 b[i] = (byte)-1; 293 } 294 for (int i = 0; i < 10000; i++) { 295 result += arrenc.encode(a, 0, size, b); 296 } 297 for (int i = 0; i < size; i++) { 298 b[i] = (byte)-1; 299 } 300 for (int i = 0; i < 10000; i++) { 301 result += arrenc.encode(a, 0, size, b); 302 } 303 if (result != size*20000 || !Arrays.equals(b, bt)) { 304 failed = true; 305 System.out.println("Failed 1: ArrayEncoder.encode char[" + SIZE + "]"); 306 } 307 for (int i = 0; i < size; i++) { 308 b[i] = (byte)-1; 309 } 310 311 System.out.println("Testing ISO_8859_1$Encode.encode() performance"); 312 result = 0; 313 start = System.currentTimeMillis(); 314 for (int i = 0; i < itrs; i++) { 315 result += arrenc.encode(a, 0, size, b); 316 } 317 end = System.currentTimeMillis(); 318 if (!Arrays.equals(b, bt)) { 319 failed = true; 320 System.out.println("Failed 2: ArrayEncoder.encode char[" + size + "]"); 321 } else { 322 System.out.println("size: " + size + " time: " + (end - start)); 323 } 324 325 if (failed) { 326 System.out.println("FAILED"); 327 System.exit(97); 328 } 329 System.out.println("PASSED"); 330 } 331 }