From b5503668e79c63fcd56d6b574bf44a714f009006 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Mon, 6 Jan 2025 22:28:16 +0800 Subject: [PATCH 01/19] vector uuid toString --- .../share/classes/java/util/UUID.java | 57 ++++++++++++++----- .../classes/jdk/internal/util/HexDigits.java | 16 ------ 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index e334f7263e46f..008c9972b363d 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -31,7 +31,7 @@ import jdk.internal.access.JavaLangAccess; import jdk.internal.access.SharedSecrets; -import jdk.internal.util.HexDigits; +import jdk.internal.misc.Unsafe; /** * A class that represents an immutable universally unique identifier (UUID). @@ -76,6 +76,7 @@ * @since 1.5 */ public final class UUID implements java.io.Serializable, Comparable { + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); /** * Explicit serialVersionUID for interoperability. @@ -466,24 +467,18 @@ public long node() { */ @Override public String toString() { - int i0 = (int) (mostSigBits >> 32); - int i1 = (int) mostSigBits; - int i2 = (int) (leastSigBits >> 32); - int i3 = (int) leastSigBits; - + long lsb = leastSigBits; + long msb = mostSigBits; byte[] buf = new byte[36]; - HexDigits.put4(buf, 0, i0 >> 16); - HexDigits.put4(buf, 4, i0); buf[8] = '-'; - HexDigits.put4(buf, 9, i1 >> 16); buf[13] = '-'; - HexDigits.put4(buf, 14, i1); buf[18] = '-'; - HexDigits.put4(buf, 19, i2 >> 16); buf[23] = '-'; - HexDigits.put4(buf, 24, i2); - HexDigits.put4(buf, 28, i3 >> 16); - HexDigits.put4(buf, 32, i3); + putHex8(buf, 0, msb >> 32, false); + putHex8(buf, 9, msb, true); + putHex8(buf, 19, lsb >> 32, true); + putHex8(buf, 28, lsb, false); + try { return jla.newStringNoRepl(buf, StandardCharsets.ISO_8859_1); } catch (CharacterCodingException cce) { @@ -491,6 +486,40 @@ public String toString() { } } + private static void putHex8(byte[] bytes, int off, long i, boolean separator) { + long e = Long.expand(i, 0x0F0F_0F0F_0F0F_0F0FL); + /* + Use long to simulate vector operations and generate 8 hexadecimal characters at a time. + ------------ + 0 = 0b0000_0000 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0 + 0x30 + (i & 0xF) => '0' + 1 = 0b0000_0001 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0 + 0x30 + (i & 0xF) => '1' + 2 = 0b0000_0010 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0 + 0x30 + (i & 0xF) => '2' + 3 = 0b0000_0011 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0 + 0x30 + (i & 0xF) => '3' + 4 = 0b0000_0100 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0 + 0x30 + (i & 0xF) => '4' + 5 = 0b0000_0101 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0 + 0x30 + (i & 0xF) => '5' + 6 = 0b0000_0110 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0 + 0x30 + (i & 0xF) => '6' + 7 = 0b0000_0111 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0 + 0x30 + (i & 0xF) => '7' + 8 = 0b0000_1000 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0 + 0x30 + (i & 0xF) => '8' + 9 = 0b0000_1001 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0 + 0x30 + (i & 0xF) => '9' + 10 = 0b0000_1010 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 39 + 0x30 + (i & 0xF) => 'a' + 11 = 0b0000_1011 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 39 + 0x30 + (i & 0xF) => 'b' + 12 = 0b0000_1100 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 39 + 0x30 + (i & 0xF) => 'c' + 13 = 0b0000_1101 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 39 + 0x30 + (i & 0xF) => 'd' + 14 = 0b0000_1110 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 39 + 0x30 + (i & 0xF) => 'e' + 15 = 0b0000_1111 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 39 + 0x30 + (i & 0xF) => 'f' + */ + long m = (e + 0x0606_0606_0606_0606L) & 0x1010_1010_1010_1010L; + long x = ((m << 1) + (m >> 1) - (m >> 4)) + + 0x3030_3030_3030_3030L + + (e & 0x0F0F_0F0F_0F0F_0F0FL); + if (separator) { + UNSAFE.putIntUnaligned(bytes, Unsafe.ARRAY_BYTE_BASE_OFFSET + off, (int) x, true); + UNSAFE.putIntUnaligned(bytes, Unsafe.ARRAY_BYTE_BASE_OFFSET + off + 5, (int) (x >>> 32), true); + } else { + UNSAFE.putLongUnaligned(bytes, Unsafe.ARRAY_BYTE_BASE_OFFSET + off, x, true); + } + } + /** * Returns a hash code for this {@code UUID}. * diff --git a/src/java.base/share/classes/jdk/internal/util/HexDigits.java b/src/java.base/share/classes/jdk/internal/util/HexDigits.java index c08db4f5b48fd..3ca016dbdf0f1 100644 --- a/src/java.base/share/classes/jdk/internal/util/HexDigits.java +++ b/src/java.base/share/classes/jdk/internal/util/HexDigits.java @@ -113,22 +113,6 @@ public static short digitPair(int i, boolean ucase) { : v; } - /** - * Insert the unsigned 2-byte integer into the buffer as 4 hexadecimal digit ASCII bytes, - * only least significant 16 bits of {@code value} are used. - * @param buffer byte buffer to copy into - * @param index insert point - * @param value to convert - */ - public static void put4(byte[] buffer, int index, int value) { - // Prepare an int value so C2 generates a 4-byte write instead of two 2-byte writes - int v = (DIGITS[value & 0xff] << 16) | DIGITS[(value >> 8) & 0xff]; - buffer[index] = (byte) v; - buffer[index + 1] = (byte) (v >> 8); - buffer[index + 2] = (byte) (v >> 16); - buffer[index + 3] = (byte) (v >> 24); - } - /** * Insert digits for long value in buffer from high index to low index. * From 266a9d849d459bb4c2945f29226697f283beedbc Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Tue, 7 Jan 2025 00:31:08 +0800 Subject: [PATCH 02/19] bug fix --- src/java.base/share/classes/java/util/UUID.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index 008c9972b363d..b725d2f9d21ee 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -32,6 +32,7 @@ import jdk.internal.access.JavaLangAccess; import jdk.internal.access.SharedSecrets; import jdk.internal.misc.Unsafe; +import static jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET; /** * A class that represents an immutable universally unique identifier (UUID). @@ -474,9 +475,9 @@ public String toString() { buf[13] = '-'; buf[18] = '-'; buf[23] = '-'; - putHex8(buf, 0, msb >> 32, false); + putHex8(buf, 0, msb >>> 32, false); putHex8(buf, 9, msb, true); - putHex8(buf, 19, lsb >> 32, true); + putHex8(buf, 19, lsb >>> 32, true); putHex8(buf, 28, lsb, false); try { @@ -513,10 +514,10 @@ private static void putHex8(byte[] bytes, int off, long i, boolean separator) { + 0x3030_3030_3030_3030L + (e & 0x0F0F_0F0F_0F0F_0F0FL); if (separator) { - UNSAFE.putIntUnaligned(bytes, Unsafe.ARRAY_BYTE_BASE_OFFSET + off, (int) x, true); - UNSAFE.putIntUnaligned(bytes, Unsafe.ARRAY_BYTE_BASE_OFFSET + off + 5, (int) (x >>> 32), true); + UNSAFE.putIntUnaligned(bytes, ARRAY_BYTE_BASE_OFFSET + off , (int) (x >>> 32), true); + UNSAFE.putIntUnaligned(bytes, ARRAY_BYTE_BASE_OFFSET + off + 5, (int) x, true); } else { - UNSAFE.putLongUnaligned(bytes, Unsafe.ARRAY_BYTE_BASE_OFFSET + off, x, true); + UNSAFE.putLongUnaligned(bytes, ARRAY_BYTE_BASE_OFFSET + off, x, true); } } From 63851e236c6389a2c042900eeda947f2c993f66c Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Tue, 7 Jan 2025 07:32:49 +0800 Subject: [PATCH 03/19] refactor --- .../share/classes/java/util/UUID.java | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index b725d2f9d21ee..01b473bd66972 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -468,17 +468,25 @@ public long node() { */ @Override public String toString() { - long lsb = leastSigBits; - long msb = mostSigBits; byte[] buf = new byte[36]; buf[8] = '-'; buf[13] = '-'; buf[18] = '-'; buf[23] = '-'; - putHex8(buf, 0, msb >>> 32, false); - putHex8(buf, 9, msb, true); - putHex8(buf, 19, lsb >>> 32, true); - putHex8(buf, 28, lsb, false); + + long x = mostSigBits, + x0 = hex8(x >>> 32), + x1 = hex8(x); + UNSAFE.putLongUnaligned(buf, ARRAY_BYTE_BASE_OFFSET, x0, false); + UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 9, (int) x1, false); + UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 14, (int) (x1 >>> 32), false); + + x = leastSigBits; + x0 = hex8(x >>> 32); + x1 = hex8(x); + UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 19, (int) x0, false); + UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 24, (int) (x0 >>> 32), false); + UNSAFE.putLongUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 28, x1, false); try { return jla.newStringNoRepl(buf, StandardCharsets.ISO_8859_1); @@ -487,7 +495,7 @@ public String toString() { } } - private static void putHex8(byte[] bytes, int off, long i, boolean separator) { + private static long hex8(long i) { long e = Long.expand(i, 0x0F0F_0F0F_0F0F_0F0FL); /* Use long to simulate vector operations and generate 8 hexadecimal characters at a time. @@ -510,15 +518,9 @@ private static void putHex8(byte[] bytes, int off, long i, boolean separator) { 15 = 0b0000_1111 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 39 + 0x30 + (i & 0xF) => 'f' */ long m = (e + 0x0606_0606_0606_0606L) & 0x1010_1010_1010_1010L; - long x = ((m << 1) + (m >> 1) - (m >> 4)) + return Long.reverseBytes(((m << 1) + (m >> 1) - (m >> 4)) + 0x3030_3030_3030_3030L - + (e & 0x0F0F_0F0F_0F0F_0F0FL); - if (separator) { - UNSAFE.putIntUnaligned(bytes, ARRAY_BYTE_BASE_OFFSET + off , (int) (x >>> 32), true); - UNSAFE.putIntUnaligned(bytes, ARRAY_BYTE_BASE_OFFSET + off + 5, (int) x, true); - } else { - UNSAFE.putLongUnaligned(bytes, ARRAY_BYTE_BASE_OFFSET + off, x, true); - } + + (e & 0x0F0F_0F0F_0F0F_0F0FL)); } /** From 010ab70c00b7c0f417127c050654a381b489d052 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Wed, 8 Jan 2025 13:37:48 +0800 Subject: [PATCH 04/19] Remove unnecessary steps --- .../share/classes/java/util/UUID.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index 01b473bd66972..fb9da85a2e9d6 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -477,16 +477,16 @@ public String toString() { long x = mostSigBits, x0 = hex8(x >>> 32), x1 = hex8(x); - UNSAFE.putLongUnaligned(buf, ARRAY_BYTE_BASE_OFFSET, x0, false); - UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 9, (int) x1, false); - UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 14, (int) (x1 >>> 32), false); + UNSAFE.putLongUnaligned(buf, ARRAY_BYTE_BASE_OFFSET, x0, true); + UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 9, (int) (x1 >>> 32), true); + UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 14, (int) x1, true); x = leastSigBits; x0 = hex8(x >>> 32); x1 = hex8(x); - UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 19, (int) x0, false); - UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 24, (int) (x0 >>> 32), false); - UNSAFE.putLongUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 28, x1, false); + UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 19, (int) (x0 >>> 32), true); + UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 24, (int) x0, true); + UNSAFE.putLongUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 28, x1, true); try { return jla.newStringNoRepl(buf, StandardCharsets.ISO_8859_1); @@ -496,7 +496,7 @@ public String toString() { } private static long hex8(long i) { - long e = Long.expand(i, 0x0F0F_0F0F_0F0F_0F0FL); + i = Long.expand(i, 0x0F0F_0F0F_0F0F_0F0FL); /* Use long to simulate vector operations and generate 8 hexadecimal characters at a time. ------------ @@ -517,10 +517,10 @@ private static long hex8(long i) { 14 = 0b0000_1110 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 39 + 0x30 + (i & 0xF) => 'e' 15 = 0b0000_1111 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 39 + 0x30 + (i & 0xF) => 'f' */ - long m = (e + 0x0606_0606_0606_0606L) & 0x1010_1010_1010_1010L; - return Long.reverseBytes(((m << 1) + (m >> 1) - (m >> 4)) + long m = (i + 0x0606_0606_0606_0606L) & 0x1010_1010_1010_1010L; + return ((m << 1) + (m >> 1) - (m >> 4)) + 0x3030_3030_3030_3030L - + (e & 0x0F0F_0F0F_0F0F_0F0FL)); + + i; } /** From 2ee96c257ba1e352c57269857aadfd5d723cd80c Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Wed, 8 Jan 2025 20:20:21 +0800 Subject: [PATCH 05/19] manual expand --- src/java.base/share/classes/java/util/UUID.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index fb9da85a2e9d6..e924015d1f1fa 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -496,7 +496,15 @@ public String toString() { } private static long hex8(long i) { - i = Long.expand(i, 0x0F0F_0F0F_0F0F_0F0FL); + // i = Long.expand(i, 0x0F0F_0F0F_0F0F_0F0FL); + i = ((i & 0xF0000000L) << 28) + |((i & 0xF000000) << 24) + |((i & 0xF00000) << 20) + |((i & 0xF0000) << 16) + |((i & 0xF000) << 12) + |((i & 0xF00) << 8) + |((i & 0xF0) << 4) + | (i & 0xF); /* Use long to simulate vector operations and generate 8 hexadecimal characters at a time. ------------ From a96cad9c54de613f2dc0a9c2eccae899a5fd172f Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Wed, 8 Jan 2025 20:56:21 +0800 Subject: [PATCH 06/19] little endian --- .../share/classes/java/util/UUID.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index e924015d1f1fa..dcb09f1337518 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -477,16 +477,16 @@ public String toString() { long x = mostSigBits, x0 = hex8(x >>> 32), x1 = hex8(x); - UNSAFE.putLongUnaligned(buf, ARRAY_BYTE_BASE_OFFSET, x0, true); - UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 9, (int) (x1 >>> 32), true); - UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 14, (int) x1, true); + UNSAFE.putLongUnaligned(buf, ARRAY_BYTE_BASE_OFFSET, x0, false); + UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 9, (int) x1, false); + UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 14, (int) (x1 >>> 32), false); x = leastSigBits; x0 = hex8(x >>> 32); x1 = hex8(x); - UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 19, (int) (x0 >>> 32), true); - UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 24, (int) x0, true); - UNSAFE.putLongUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 28, x1, true); + UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 19, (int) (x0), false); + UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 24, (int) (x0 >>> 32), false); + UNSAFE.putLongUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 28, x1, false); try { return jla.newStringNoRepl(buf, StandardCharsets.ISO_8859_1); @@ -496,15 +496,15 @@ public String toString() { } private static long hex8(long i) { - // i = Long.expand(i, 0x0F0F_0F0F_0F0F_0F0FL); - i = ((i & 0xF0000000L) << 28) - |((i & 0xF000000) << 24) - |((i & 0xF00000) << 20) - |((i & 0xF0000) << 16) - |((i & 0xF000) << 12) - |((i & 0xF00) << 8) - |((i & 0xF0) << 4) - | (i & 0xF); + // i = Long.reverseBytes(Long.expand(i, 0x0F0F_0F0F_0F0F_0F0FL)); + i = ((i & 0xF0000000L) >> 28) + |((i & 0xF000000L) >> 16) + |((i & 0xF00000L) >> 4) + |((i & 0xF0000L) << 8) + |((i & 0xF000L) << 20) + |((i & 0xF00L) << 32) + |((i & 0xF0L) << 44) + |((i & 0xFL) << 56); /* Use long to simulate vector operations and generate 8 hexadecimal characters at a time. ------------ From f7ac21ab56dc37abe0b30b06d22e218ef66b44d9 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Wed, 8 Jan 2025 21:09:58 +0800 Subject: [PATCH 07/19] ues Long.expand --- src/java.base/share/classes/java/util/UUID.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index dcb09f1337518..eac42f4012639 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -496,15 +496,7 @@ public String toString() { } private static long hex8(long i) { - // i = Long.reverseBytes(Long.expand(i, 0x0F0F_0F0F_0F0F_0F0FL)); - i = ((i & 0xF0000000L) >> 28) - |((i & 0xF000000L) >> 16) - |((i & 0xF00000L) >> 4) - |((i & 0xF0000L) << 8) - |((i & 0xF000L) << 20) - |((i & 0xF00L) << 32) - |((i & 0xF0L) << 44) - |((i & 0xFL) << 56); + i = Long.reverseBytes(Long.expand(i, 0x0F0F_0F0F_0F0F_0F0FL)); /* Use long to simulate vector operations and generate 8 hexadecimal characters at a time. ------------ From 73ef535a6d5c6ab91979e0fe8976ff4f71666f00 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Thu, 9 Jan 2025 07:28:17 +0800 Subject: [PATCH 08/19] use ByteArrayLittleEndian --- .../share/classes/java/util/UUID.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index eac42f4012639..c1b1fe9ff62f2 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -31,8 +31,7 @@ import jdk.internal.access.JavaLangAccess; import jdk.internal.access.SharedSecrets; -import jdk.internal.misc.Unsafe; -import static jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET; +import jdk.internal.util.ByteArrayLittleEndian; /** * A class that represents an immutable universally unique identifier (UUID). @@ -77,8 +76,6 @@ * @since 1.5 */ public final class UUID implements java.io.Serializable, Comparable { - private static final Unsafe UNSAFE = Unsafe.getUnsafe(); - /** * Explicit serialVersionUID for interoperability. */ @@ -474,19 +471,21 @@ public String toString() { buf[18] = '-'; buf[23] = '-'; +// Unsafe UNSAFE = Unsafe.getUnsafe(); + long x = mostSigBits, x0 = hex8(x >>> 32), x1 = hex8(x); - UNSAFE.putLongUnaligned(buf, ARRAY_BYTE_BASE_OFFSET, x0, false); - UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 9, (int) x1, false); - UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 14, (int) (x1 >>> 32), false); + ByteArrayLittleEndian.setLong(buf, 0, x0); + ByteArrayLittleEndian.setInt(buf, 9, (int) x1); + ByteArrayLittleEndian.setInt(buf, 14, (int) (x1 >>> 32)); x = leastSigBits; x0 = hex8(x >>> 32); x1 = hex8(x); - UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 19, (int) (x0), false); - UNSAFE.putIntUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 24, (int) (x0 >>> 32), false); - UNSAFE.putLongUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + 28, x1, false); + ByteArrayLittleEndian.setInt(buf, 19, (int) (x0)); + ByteArrayLittleEndian.setInt(buf, 24, (int) (x0 >>> 32)); + ByteArrayLittleEndian.setLong(buf, 28, x1); try { return jla.newStringNoRepl(buf, StandardCharsets.ISO_8859_1); From 8367b95c3f3c19d0265aeaf3285e4b25f053fd29 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Thu, 9 Jan 2025 07:30:57 +0800 Subject: [PATCH 09/19] add comments --- src/java.base/share/classes/java/util/UUID.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index c1b1fe9ff62f2..ac63f04849543 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -494,6 +494,11 @@ public String toString() { } } + /** + * Extract the least significant 4 bytes from the input integer i, convert each byte into its corresponding 2-digit + * hexadecimal representation, concatenate these hexadecimal strings into one continuous string, and then interpret + * this string as a hexadecimal number to form and return a long value. + */ private static long hex8(long i) { i = Long.reverseBytes(Long.expand(i, 0x0F0F_0F0F_0F0F_0F0FL)); /* From 7b5287e550d7e4ed89c17139852b26ea5e156630 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Sat, 11 Jan 2025 11:33:58 +0800 Subject: [PATCH 10/19] from j3graham --- src/java.base/share/classes/java/util/UUID.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index ac63f04849543..78ac703fa0adf 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -500,7 +500,15 @@ public String toString() { * this string as a hexadecimal number to form and return a long value. */ private static long hex8(long i) { - i = Long.reverseBytes(Long.expand(i, 0x0F0F_0F0F_0F0F_0F0FL)); + // i = Long.reverseBytes(Long.expand(i, 0x0F0F_0F0F_0F0F_0F0FL)); + long t = i << 16; + i = (i & ~0xFFFF00000000L) | (t & 0xFFFF00000000L); + t = i << 8; + i = (i & ~0xFF000000FF0000L) | (t & 0xFF000000FF0000L); + t = i << 4; + i = (i & ~0xF000F000F000F00L) | (t & 0xF000F000F000F00L); + i = Long.reverseBytes(i & 0x0F0F_0F0F_0F0F_0F0FL); + /* Use long to simulate vector operations and generate 8 hexadecimal characters at a time. ------------ From c513087056be8c1e1a915625e0b425a7ecbb21d6 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Sat, 11 Jan 2025 12:29:15 +0800 Subject: [PATCH 11/19] refactor --- .../share/classes/java/util/UUID.java | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index 78ac703fa0adf..9b1401e3469e4 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -500,15 +500,7 @@ public String toString() { * this string as a hexadecimal number to form and return a long value. */ private static long hex8(long i) { - // i = Long.reverseBytes(Long.expand(i, 0x0F0F_0F0F_0F0F_0F0FL)); - long t = i << 16; - i = (i & ~0xFFFF00000000L) | (t & 0xFFFF00000000L); - t = i << 8; - i = (i & ~0xFF000000FF0000L) | (t & 0xFF000000FF0000L); - t = i << 4; - i = (i & ~0xF000F000F000F00L) | (t & 0xF000F000F000F00L); - i = Long.reverseBytes(i & 0x0F0F_0F0F_0F0F_0F0FL); - + i = expand(i); /* Use long to simulate vector operations and generate 8 hexadecimal characters at a time. ------------ @@ -530,9 +522,22 @@ private static long hex8(long i) { 15 = 0b0000_1111 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 39 + 0x30 + (i & 0xF) => 'f' */ long m = (i + 0x0606_0606_0606_0606L) & 0x1010_1010_1010_1010L; - return ((m << 1) + (m >> 1) - (m >> 4)) + return Long.reverseBytes(((m << 1) + (m >> 1) - (m >> 4)) + 0x3030_3030_3030_3030L - + i; + + i); + } + + /** + * A faster alternative that is functionally equivalent to Long.expand(i, 0x0F0F_0F0F_0F0F_0F0FL) + */ + private static long expand(long i) { + long t = i << 16; + i = (i & ~0xFFFF00000000L) | (t & 0xFFFF00000000L); + t = i << 8; + i = (i & ~0xFF000000FF0000L) | (t & 0xFF000000FF0000L); + t = i << 4; + i = (i & ~0xF000F000F000F00L) | (t & 0xF000F000F000F00L); + return i & 0x0F0F_0F0F_0F0F_0F0FL; } /** From 1059d39f3fb3dc58bafb78cf71d387a140130b6f Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Fri, 4 Apr 2025 21:51:08 +0800 Subject: [PATCH 12/19] use Long.expand --- src/java.base/share/classes/java/util/UUID.java | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index c16a6d088ae6f..28bb1aaa8c0a2 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -496,7 +496,7 @@ public String toString() { * this string as a hexadecimal number to form and return a long value. */ private static long hex8(long i) { - i = expand(i); + i = Long.expand(i, 0x0F0F_0F0F_0F0F_0F0FL); /* Use long to simulate vector operations and generate 8 hexadecimal characters at a time. ------------ @@ -523,19 +523,6 @@ private static long hex8(long i) { + i); } - /** - * A faster alternative that is functionally equivalent to Long.expand(i, 0x0F0F_0F0F_0F0F_0F0FL) - */ - private static long expand(long i) { - long t = i << 16; - i = (i & ~0xFFFF00000000L) | (t & 0xFFFF00000000L); - t = i << 8; - i = (i & ~0xFF000000FF0000L) | (t & 0xFF000000FF0000L); - t = i << 4; - i = (i & ~0xF000F000F000F00L) | (t & 0xF000F000F000F00L); - return i & 0x0F0F_0F0F_0F0F_0F0FL; - } - /** * Returns a hash code for this {@code UUID}. * From 93d283e4ceefbb31702bcbd4a025368f6c5aca95 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Sat, 5 Apr 2025 00:48:07 +0800 Subject: [PATCH 13/19] Remove redundant comments --- src/java.base/share/classes/java/util/UUID.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index 28bb1aaa8c0a2..1363b48cffca7 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -467,8 +467,6 @@ public String toString() { buf[18] = '-'; buf[23] = '-'; -// Unsafe UNSAFE = Unsafe.getUnsafe(); - long x = mostSigBits, x0 = hex8(x >>> 32), x1 = hex8(x); From 55223571d075aaa791d610bccf17f074428d2e29 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Sat, 5 Apr 2025 13:11:36 +0800 Subject: [PATCH 14/19] simplify code --- .../share/classes/java/util/UUID.java | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index 1363b48cffca7..7ba5b99ca0e91 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -467,19 +467,15 @@ public String toString() { buf[18] = '-'; buf[23] = '-'; - long x = mostSigBits, - x0 = hex8(x >>> 32), - x1 = hex8(x); - ByteArrayLittleEndian.setLong(buf, 0, x0); - ByteArrayLittleEndian.setInt(buf, 9, (int) x1); - ByteArrayLittleEndian.setInt(buf, 14, (int) (x1 >>> 32)); - - x = leastSigBits; - x0 = hex8(x >>> 32); - x1 = hex8(x); - ByteArrayLittleEndian.setInt(buf, 19, (int) (x0)); - ByteArrayLittleEndian.setInt(buf, 24, (int) (x0 >>> 32)); - ByteArrayLittleEndian.setLong(buf, 28, x1); + ByteArrayLittleEndian.setLong(buf, 0, hex8(mostSigBits >>> 32)); + long x0 = hex8(mostSigBits); + ByteArrayLittleEndian.setInt(buf, 9, (int) x0); + ByteArrayLittleEndian.setInt(buf, 14, (int) (x0 >>> 32)); + + long x1 = hex8(leastSigBits >>> 32); + ByteArrayLittleEndian.setInt(buf, 19, (int) (x1)); + ByteArrayLittleEndian.setInt(buf, 24, (int) (x1 >>> 32)); + ByteArrayLittleEndian.setLong(buf, 28, hex8(leastSigBits)); try { return jla.newStringNoRepl(buf, StandardCharsets.ISO_8859_1); From 4e62d43ce302324d79cc0cd5eab939bc7456342f Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Tue, 20 May 2025 07:31:16 +0800 Subject: [PATCH 15/19] hex8 comments --- .../share/classes/java/util/UUID.java | 50 ++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index 118f37220d3b4..c43799ee72ad2 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -485,12 +485,44 @@ public String toString() { } /** - * Extract the least significant 4 bytes from the input integer i, convert each byte into its corresponding 2-digit - * hexadecimal representation, concatenate these hexadecimal strings into one continuous string, and then interpret - * this string as a hexadecimal number to form and return a long value. + * Converts 4 bytes from a long input into an 8-character hexadecimal string encoded as a long value, + * using vectorized bitwise operations for high performance. + * + * Algorithm Description: + * 1. Byte Expansion Phase: + * - Extracts 8 nibbles (4-bit values) from the 4 input bytes using 0x0F mask pattern + * - Expands each byte into two 16-bit sections using Long.expand() + * - Final layout: 0xAABBCCDD -> 0x0A0B0C0D0A0B0C0D (nibble separation) + * + * 2. Hex Conversion Phase (Parallel Computation): + * a. Carry Detection: Adds 6 to each nibble (0x06 per byte) + * - Generates carry bit (0x10) for values >= 10 + * - Mask: 0x1010_1010_1010_1010 identifies hex letters (a-f) + * b. ASCII Calculation: + * - Base value: 0x30 ('0' character) + * - Letter adjustment: 39 (0x27) for values >=10 using bitwise magic: + * (carry_mask << 1) + (carry_mask >> 1) - (carry_mask >> 4) = 0x27 + * c. Parallel Addition: Combines base/letter adjustment with original nibbles + * + * 3. Byte Order Correction: + * - Reverses byte order to match big-endian string representation + * + * Performance Considerations: + * - Processes all 8 nibbles simultaneously using bitwise operations (~1 cycle) + * - Eliminates: + * - Loop overhead (traditional 8-iteration approach) + * - Branch mispredictions (no if/else for letter/digit) + * - Multiple memory accesses (works entirely in registers) + * - Achieves O(1) time complexity vs O(n) for iterative approaches + * - Uses 6 arithmetic/logical operations vs 40+ for naive implementation + * + * @param i The input value containing up to 4 bytes of data in its least significant bits + * @return A long value representing the concatenated hexadecimal string of the 4 input bytes */ private static long hex8(long i) { + // Expand bytes to separated nibbles: 0xAABBCCDD -> 0x0A0B0C0D0A0B0C0D i = Long.expand(i, 0x0F0F_0F0F_0F0F_0F0FL); + /* Use long to simulate vector operations and generate 8 hexadecimal characters at a time. ------------ @@ -511,10 +543,16 @@ private static long hex8(long i) { 14 = 0b0000_1110 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 39 + 0x30 + (i & 0xF) => 'e' 15 = 0b0000_1111 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 39 + 0x30 + (i & 0xF) => 'f' */ + + // Detect nibbles >= 10 using carry propagation (0x06 addition per nibble) long m = (i + 0x0606_0606_0606_0606L) & 0x1010_1010_1010_1010L; - return Long.reverseBytes(((m << 1) + (m >> 1) - (m >> 4)) - + 0x3030_3030_3030_3030L - + i); + + // Vectorized ASCII conversion: (0x30 base + nibble) + (0x27 adjustment if >=10) + return Long.reverseBytes( + ((m << 1) + (m >> 1) - (m >> 4)) // 0x27 mask generator + + 0x3030_3030_3030_3030L // Base '0' characters + + i // Nibble values + ); } /** From 3b94f81f2f832ad29fb4fe0edee72e8da9b73c91 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Tue, 20 May 2025 07:48:29 +0800 Subject: [PATCH 16/19] hex8 comments --- .../share/classes/java/util/UUID.java | 122 +++++++++--------- 1 file changed, 64 insertions(+), 58 deletions(-) diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index c43799ee72ad2..8e18926c74fa5 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -485,73 +485,79 @@ public String toString() { } /** - * Converts 4 bytes from a long input into an 8-character hexadecimal string encoded as a long value, - * using vectorized bitwise operations for high performance. - * - * Algorithm Description: - * 1. Byte Expansion Phase: - * - Extracts 8 nibbles (4-bit values) from the 4 input bytes using 0x0F mask pattern - * - Expands each byte into two 16-bit sections using Long.expand() - * - Final layout: 0xAABBCCDD -> 0x0A0B0C0D0A0B0C0D (nibble separation) - * - * 2. Hex Conversion Phase (Parallel Computation): - * a. Carry Detection: Adds 6 to each nibble (0x06 per byte) - * - Generates carry bit (0x10) for values >= 10 - * - Mask: 0x1010_1010_1010_1010 identifies hex letters (a-f) - * b. ASCII Calculation: - * - Base value: 0x30 ('0' character) - * - Letter adjustment: 39 (0x27) for values >=10 using bitwise magic: - * (carry_mask << 1) + (carry_mask >> 1) - (carry_mask >> 4) = 0x27 - * c. Parallel Addition: Combines base/letter adjustment with original nibbles - * - * 3. Byte Order Correction: - * - Reverses byte order to match big-endian string representation - * - * Performance Considerations: - * - Processes all 8 nibbles simultaneously using bitwise operations (~1 cycle) - * - Eliminates: - * - Loop overhead (traditional 8-iteration approach) - * - Branch mispredictions (no if/else for letter/digit) - * - Multiple memory accesses (works entirely in registers) - * - Achieves O(1) time complexity vs O(n) for iterative approaches - * - Uses 6 arithmetic/logical operations vs 40+ for naive implementation - * - * @param i The input value containing up to 4 bytes of data in its least significant bits - * @return A long value representing the concatenated hexadecimal string of the 4 input bytes + * Efficiently converts 8 hexadecimal digits to their ASCII representation using SIMD-style vector operations. + * This method processes multiple digits in parallel by treating a long value as eight 8-bit lanes, + * achieving significantly better performance compared to traditional loop-based conversion. + * + *

The conversion algorithm works as follows: + *

+     * 1. Input expansion: Each 4-bit hex digit is expanded to 8 bits
+     * 2. Vector processing:
+     *    - Add 6 to each digit: triggers carry flag for a-f digits
+     *    - Mask with 0x10 pattern to isolate carry flags
+     *    - Calculate ASCII adjustment: (carry << 1) + (carry >> 1) - (carry >> 4)
+     *    - Add ASCII '0' base (0x30) and original value
+     * 3. Byte order adjustment for final output
+     * 
+ * + *

Performance characteristics: + *

    + *
  • Processes 8 digits in parallel using vector operations + *
  • Avoids branching and loops completely + *
  • Uses only integer arithmetic and bit operations + *
  • Constant time execution regardless of input values + *
+ * + *

ASCII conversion mapping: + *

    + *
  • Digits 0-9 → ASCII '0'-'9' (0x30-0x39) + *
  • Digits a-f → ASCII 'a'-'f' (0x61-0x66) + *
+ * + * @param input A long containing 8 hex digits (each digit must be 0-15) + * @return A long containing 8 ASCII bytes representing the hex digits + * + * @implNote The implementation leverages CPU vector processing capabilities through + * long integer operations. The algorithm is based on the observation that + * ASCII hex digits have a specific pattern that can be computed efficiently + * using carry flag manipulation. + * + * @example + *
+     * Input:  0x0123456789ABCDEF
+     * Output: 0x3031323334353637 ('0','1','2','3','4','5','6','7' in ASCII)
+     * 
+ * + * @see Long#reverseBytes(long) */ private static long hex8(long i) { - // Expand bytes to separated nibbles: 0xAABBCCDD -> 0x0A0B0C0D0A0B0C0D + // Expand each 4-bit group into 8 bits, spreading them out in the long value: 0xAABBCCDD -> 0x0A0B0C0D0A0B0C0D i = Long.expand(i, 0x0F0F_0F0F_0F0F_0F0FL); /* - Use long to simulate vector operations and generate 8 hexadecimal characters at a time. - ------------ - 0 = 0b0000_0000 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0 + 0x30 + (i & 0xF) => '0' - 1 = 0b0000_0001 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0 + 0x30 + (i & 0xF) => '1' - 2 = 0b0000_0010 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0 + 0x30 + (i & 0xF) => '2' - 3 = 0b0000_0011 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0 + 0x30 + (i & 0xF) => '3' - 4 = 0b0000_0100 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0 + 0x30 + (i & 0xF) => '4' - 5 = 0b0000_0101 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0 + 0x30 + (i & 0xF) => '5' - 6 = 0b0000_0110 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0 + 0x30 + (i & 0xF) => '6' - 7 = 0b0000_0111 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0 + 0x30 + (i & 0xF) => '7' - 8 = 0b0000_1000 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0 + 0x30 + (i & 0xF) => '8' - 9 = 0b0000_1001 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0 + 0x30 + (i & 0xF) => '9' - 10 = 0b0000_1010 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 39 + 0x30 + (i & 0xF) => 'a' - 11 = 0b0000_1011 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 39 + 0x30 + (i & 0xF) => 'b' - 12 = 0b0000_1100 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 39 + 0x30 + (i & 0xF) => 'c' - 13 = 0b0000_1101 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 39 + 0x30 + (i & 0xF) => 'd' - 14 = 0b0000_1110 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 39 + 0x30 + (i & 0xF) => 'e' - 15 = 0b0000_1111 => m = ((i + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 39 + 0x30 + (i & 0xF) => 'f' + * This method efficiently converts 8 hexadecimal digits simultaneously using vector operations + * The algorithm works as follows: + * + * For input values 0-15: + * - For digits 0-9: converts to ASCII '0'-'9' (0x30-0x39) + * - For digits 10-15: converts to ASCII 'a'-'f' (0x61-0x66) + * + * The conversion process: + * 1. Add 6 to each 4-bit group: i + 0x0606_0606_0606_0606L + * 2. Mask to get the adjustment flags: & 0x1010_1010_1010_1010L + * 3. Calculate the offset: (m << 1) + (m >> 1) - (m >> 4) + * - For 0-9: offset = 0 + * - For a-f: offset = 39 (to bridge the gap between '9' and 'a' in ASCII) + * 4. Add ASCII '0' base (0x30) and the original value + * 5. Reverse byte order for correct positioning */ - - // Detect nibbles >= 10 using carry propagation (0x06 addition per nibble) long m = (i + 0x0606_0606_0606_0606L) & 0x1010_1010_1010_1010L; - // Vectorized ASCII conversion: (0x30 base + nibble) + (0x27 adjustment if >=10) + // Calculate final ASCII values and reverse bytes for proper ordering return Long.reverseBytes( - ((m << 1) + (m >> 1) - (m >> 4)) // 0x27 mask generator - + 0x3030_3030_3030_3030L // Base '0' characters - + i // Nibble values + ((m << 1) + (m >> 1) - (m >> 4)) + + 0x3030_3030_3030_3030L // Add ASCII '0' base to all digits + + i // Add original values ); } From f9904389569f3d98a245f487fa34bc01e9c67dcd Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Wed, 21 May 2025 08:46:37 +0800 Subject: [PATCH 17/19] fix comments, from @j3graham --- src/java.base/share/classes/java/util/UUID.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index 8e18926c74fa5..42521fdeddad7 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -531,7 +531,7 @@ public String toString() { * @see Long#reverseBytes(long) */ private static long hex8(long i) { - // Expand each 4-bit group into 8 bits, spreading them out in the long value: 0xAABBCCDD -> 0x0A0B0C0D0A0B0C0D + // Expand each 4-bit group into 8 bits, spreading them out in the long value: 0xAABBCCDD -> 0xA0A0B0B0C0C0D0D i = Long.expand(i, 0x0F0F_0F0F_0F0F_0F0FL); /* From 61e3faeeddd297564da5d3f9c42c937b03e51b85 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Wed, 21 May 2025 08:47:37 +0800 Subject: [PATCH 18/19] add comments, from @j3graham --- src/java.base/share/classes/java/util/UUID.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index 42521fdeddad7..f77d54b3a8328 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -467,6 +467,8 @@ public String toString() { buf[18] = '-'; buf[23] = '-'; + // Although the UUID byte ordering is defined to be big-endian, ByteArrayLittleEndian is used here to optimize + // for the most common architectures. hex8 reverses the order internally. ByteArrayLittleEndian.setLong(buf, 0, hex8(mostSigBits >>> 32)); long x0 = hex8(mostSigBits); ByteArrayLittleEndian.setInt(buf, 9, (int) x0); From 8d0e8fd3a55c8ff193cd1134ba25e99b7ffce40c Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Wed, 21 May 2025 08:54:15 +0800 Subject: [PATCH 19/19] fix comments, from @j3graham --- src/java.base/share/classes/java/util/UUID.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index f77d54b3a8328..5961fce9cb23c 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -526,8 +526,8 @@ public String toString() { * * @example *
-     * Input:  0x0123456789ABCDEF
-     * Output: 0x3031323334353637 ('0','1','2','3','4','5','6','7' in ASCII)
+     * Input:  0xABCDEF01
+     * Output: 3130666564636261 ('1','0','f','e','d','c','b','a' in ASCII)
      * 
* * @see Long#reverseBytes(long)