On Tue, 11 Jun 2024 11:35:28 GMT, Shaojin Wen <d...@openjdk.org> wrote:
>> After PR https://github.com/openjdk/jdk/pull/16245, C2 optimizes stores into >> primitive arrays by combining values into larger stores. >> >> This PR rewrites the code of appendNull and append(boolean) methods so that >> these two methods can be optimized by C2. > > Shaojin Wen has updated the pull request incrementally with one additional > commit since the last revision: > > revert below stand-alone reproducer, But StringUTF16.putChar is an instrinsic method and cannot be simulated. import java.nio.ByteOrder; import java.util.Arrays; public class AppendNullTest { public static class StringBuilder { byte[] value; byte coder; int count; public StringBuilder(boolean utf16) { value = new byte[0]; coder = (byte) (utf16 ? 1 : 0); } public static boolean canEncode(char cp) { return cp <= 0xff; } private StringBuilder appendNull() throws Throwable { int count = this.count; ensureCapacityInternal(count + 4); byte[] val = this.value; if (isLatin1()) { val[count ] = 'n'; val[count + 1] = 'u'; val[count + 2] = 'l'; val[count + 3] = 'l'; } else { StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l'); } this.count = count + 4; return this; } public StringBuilder append(boolean b) throws Throwable { int count = this.count; int spaceNeeded = count + (b ? 4 : 5); ensureCapacityInternal(spaceNeeded); byte[] val = this.value; if (isLatin1()) { if (b) { val[count ] = 't'; val[count + 1] = 'r'; val[count + 2] = 'u'; val[count + 3] = 'e'; } else { val[count ] = 'f'; val[count + 1] = 'a'; val[count + 2] = 'l'; val[count + 3] = 's'; val[count + 4] = 'e'; } } else { if (b) { StringUTF16.putCharsAt(val, count, 't', 'r', 'u', 'e'); } else { StringUTF16.putCharsAt(val, count, 'f', 'a', 'l', 's', 'e'); } } this.count = spaceNeeded; return this; } private void ensureCapacityInternal(int minimumCapacity) { int oldCapacity = value.length >> coder; if (minimumCapacity - oldCapacity > 0) { value = Arrays.copyOf(value, newCapacity(minimumCapacity) << coder); } } private int newCapacity(int minCapacity) { int oldLength = value.length; int newLength = minCapacity << coder; int growth = newLength - oldLength; int length = oldLength + Math.max(growth, oldLength + (2 << coder)); return length >> coder; } final boolean isLatin1() { return coder == 0; } public void clear() { int count = 0; coder = 0; } } static class StringUTF16 { public static void putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4) throws Throwable { putChar(value, i , c1); putChar(value, i + 1, c2); putChar(value, i + 2, c3); putChar(value, i + 3, c4); } public static void putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4, char c5) throws Throwable { putChar(value, i , c1); putChar(value, i + 1, c2); putChar(value, i + 2, c3); putChar(value, i + 3, c4); putChar(value, i + 4, c5); } private static final int HI_BYTE_SHIFT; private static final int LO_BYTE_SHIFT; static { if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { HI_BYTE_SHIFT = 8; LO_BYTE_SHIFT = 0; } else { HI_BYTE_SHIFT = 0; LO_BYTE_SHIFT = 8; } } static void putChar(byte[] val, int index, int c) { index <<= 1; val[index++] = (byte)(c >> HI_BYTE_SHIFT); val[index] = (byte)(c >> LO_BYTE_SHIFT); } } public static void main(String[] args) throws Throwable { StringBuilder sb = new StringBuilder(true); for (int i = 0; i < 1_000_000; i++) { sb.appendNull().appendNull().appendNull().appendNull().appendNull(); // sb.append(true).append(false).append(true).append(false).append(true).append(false); sb.clear(); } } } ------------- PR Comment: https://git.openjdk.org/jdk/pull/19626#issuecomment-2162441299