|
1 | 1 | /*
|
2 |
| - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. |
| 2 | + * Copyright (c) 2018, Red Hat Inc. All rights reserved. |
3 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
4 | 4 | *
|
5 | 5 | * This code is free software; you can redistribute it and/or modify it
|
|
23 | 23 |
|
24 | 24 | /*
|
25 | 25 | * @test
|
26 |
| - * @bug 8204479 8253191 |
| 26 | + * @bug 8204479 |
| 27 | + * @summary Bitwise AND on byte value sometimes produces wrong result |
27 | 28 | *
|
28 |
| - * @library /test/lib |
29 |
| - * @modules java.base/jdk.internal.vm.annotation |
30 |
| - * |
31 |
| - * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation compiler.c2.TestUnsignedByteCompare |
| 29 | + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation |
| 30 | + * -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -Xcomp -XX:-Inline |
| 31 | + * compiler.c2.TestUnsignedByteCompare |
32 | 32 | */
|
33 |
| -package compiler.c2; |
34 | 33 |
|
35 |
| -import java.lang.invoke.*; |
36 |
| -import jdk.internal.vm.annotation.DontInline; |
37 |
| -import jdk.test.lib.Asserts; |
| 34 | +package compiler.c2; |
38 | 35 |
|
39 | 36 | public class TestUnsignedByteCompare {
|
40 | 37 |
|
41 |
| - @DontInline static boolean testByteGT0(byte[] val) { return (val[0] & mask()) > 0; } |
42 |
| - @DontInline static boolean testByteGE0(byte[] val) { return (val[0] & mask()) >= 0; } |
43 |
| - @DontInline static boolean testByteEQ0(byte[] val) { return (val[0] & mask()) == 0; } |
44 |
| - @DontInline static boolean testByteNE0(byte[] val) { return (val[0] & mask()) != 0; } |
45 |
| - @DontInline static boolean testByteLE0(byte[] val) { return (val[0] & mask()) <= 0; } |
46 |
| - @DontInline static boolean testByteLT0(byte[] val) { return (val[0] & mask()) < 0; } |
| 38 | + static int p, n; |
47 | 39 |
|
48 |
| - static void testValue(byte b) { |
49 |
| - byte[] bs = new byte[] { b }; |
50 |
| - Asserts.assertEquals(((b & mask()) > 0), testByteGT0(bs), errorMessage(b, "GT0")); |
51 |
| - Asserts.assertEquals(((b & mask()) >= 0), testByteGE0(bs), errorMessage(b, "GE0")); |
52 |
| - Asserts.assertEquals(((b & mask()) == 0), testByteEQ0(bs), errorMessage(b, "EQ0")); |
53 |
| - Asserts.assertEquals(((b & mask()) != 0), testByteNE0(bs), errorMessage(b, "NE0")); |
54 |
| - Asserts.assertEquals(((b & mask()) <= 0), testByteLE0(bs), errorMessage(b, "LE0")); |
55 |
| - Asserts.assertEquals(((b & mask()) < 0), testByteLT0(bs), errorMessage(b, "LT0")); |
| 40 | + static void report(byte[] ba, int i, boolean failed) { |
| 41 | + // Enable for debugging: |
| 42 | + // System.out.println((failed ? "Failed" : "Passed") + " with: " + ba[i] + " at " + i); |
56 | 43 | }
|
57 | 44 |
|
58 |
| - public static void main(String[] args) { |
59 |
| - for (int mask = 0; mask <= 0xFF; mask++) { |
60 |
| - setMask(mask); |
61 |
| - for (int i = 0; i < 20_000; i++) { |
62 |
| - testValue((byte) i); |
| 45 | + static void m1(byte[] ba) { |
| 46 | + for (int i = 0; i < ba.length; i++) { |
| 47 | + if ((ba[i] & 0xFF) < 0x10) { |
| 48 | + p++; |
| 49 | + report(ba, i, true); |
| 50 | + } else { |
| 51 | + n++; |
| 52 | + report(ba, i, false); |
63 | 53 | }
|
64 | 54 | }
|
65 |
| - System.out.println("TEST PASSED"); |
66 | 55 | }
|
67 | 56 |
|
68 |
| - static String errorMessage(byte b, String type) { |
69 |
| - return String.format("%s: val=0x%x mask=0x%x", type, b, mask()); |
| 57 | + static void m2(byte[] ba) { |
| 58 | + for (int i = 0; i < ba.length; i++) { |
| 59 | + if (((ba[i] & 0xFF) & 0x80) < 0) { |
| 60 | + p++; |
| 61 | + report(ba, i, true); |
| 62 | + } else { |
| 63 | + n++; |
| 64 | + report(ba, i, false); |
| 65 | + } |
| 66 | + } |
70 | 67 | }
|
71 | 68 |
|
72 |
| - // Mutable mask as a compile-time constant. |
| 69 | + static public void main(String[] args) { |
| 70 | + final int tries = 1_000; |
| 71 | + final int count = 1_000; |
73 | 72 |
|
74 |
| - private static final CallSite MASK_CS = new MutableCallSite(MethodType.methodType(int.class)); |
75 |
| - private static final MethodHandle MASK_MH = MASK_CS.dynamicInvoker(); |
| 73 | + byte[] ba = new byte[count]; |
76 | 74 |
|
77 |
| - static int mask() { |
78 |
| - try { |
79 |
| - return (int) MASK_MH.invokeExact(); |
80 |
| - } catch (Throwable t) { |
81 |
| - throw new InternalError(t); // should NOT happen |
| 75 | + for (int i = 0; i < count; i++) { |
| 76 | + int v = -(i % 126 + 1); |
| 77 | + ba[i] = (byte)v; |
82 | 78 | }
|
83 |
| - } |
84 | 79 |
|
85 |
| - static void setMask(int mask) { |
86 |
| - MethodHandle constant = MethodHandles.constant(int.class, mask); |
87 |
| - MASK_CS.setTarget(constant); |
| 80 | + for (int t = 0; t < tries; t++) { |
| 81 | + m1(ba); |
| 82 | + if (p != 0) { |
| 83 | + throw new IllegalStateException("m1 error: p = " + p + ", n = " + n); |
| 84 | + } |
| 85 | + } |
| 86 | + |
| 87 | + for (int t = 0; t < tries; t++) { |
| 88 | + m2(ba); |
| 89 | + if (p != 0) { |
| 90 | + throw new IllegalStateException("m2 error: p = " + p + ", n = " + n); |
| 91 | + } |
| 92 | + } |
88 | 93 | }
|
89 | 94 | }
|
0 commit comments