RFR: 8366224: Introduce DecimalDigits.appendPair for efficient two-digit formatting and refactor DateTimeHelper [v22]

Shaojin Wen swen at openjdk.org
Fri Nov 14 05:20:14 UTC 2025


On Fri, 14 Nov 2025 04:46:26 GMT, Shaojin Wen <swen at openjdk.org> wrote:

>> This PR introduces a new efficient API for appending two-digit integers to StringBuilders and refactors DateTimeHelper to leverage this new functionality.
>> 
>> Changes include:
>> 
>> 1. New `appendPair` method for efficient two-digit integer formatting (00-99):
>>    - Added `AbstractStringBuilder.appendLatin1(char c1, char c2)` with core implementation
>>    - Added `JavaLangAccess.appendPair(StringBuilder, char c1, char c2)` for internal access
>>    - Added `DecimalDigits.appendPair(StringBuilder, int)` public static utility method
>>    - Enhanced Javadoc documentation for all new methods
>> 
>> 2. Refactored `DateTimeHelper` to use the new `DecimalDigits.appendPair`:
>>    - Updated `DateTimeHelper.formatTo` methods for `LocalDate` and `LocalTime`
>>    - Replaced manual formatting logic with the new efficient two-digit appending
>>    - Improved code clarity and consistency in date/time formatting
>> 
>> These changes improve code clarity and performance when formatting two-digit numbers, particularly in date/time formatting scenarios.
>
> Shaojin Wen has updated the pull request incrementally with one additional commit since the last revision:
> 
>   remove JLA

In the current version 35b98cb891207af7eaaa42503c0c872ec68771c6, run the following test:


make test TEST="micro:java.time.ToStringBench.localDateToString" MICRO="VM_OPTIONS=-XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=TraceMergeStores,jdk.internal.util.DecimalDigits::appendQuad,SUCCESS" 


The output is as follows:


[TraceMergeStores]: Replace
 841  StoreB  === 881 806 833 53  [[ 846 ]]  @byte[int:>=0] (java/lang/Cloneable,java/io/Serializable):NotNull:exact+any *, idx=7;  Memory: @byte[int:>=0] (java/lang/Cloneable,java/io/Serializable):NotNull:exact+any *, idx=7;
 846  StoreB  === 881 841 844 129  [[ 851 ]]  @byte[int:>=0] (java/lang/Cloneable,java/io/Serializable):NotNull:exact+any *, idx=7;  Memory: @byte[int:>=0] (java/lang/Cloneable,java/io/Serializable):NotNull:exact+any *, idx=7;
[TraceMergeStores]: with
  53  LoadS  === 5 7 51  [[ 129 615 533 871 841 515 303 649 689 902 ]]  @short[int:>=0] (java/lang/Cloneable,java/io/Serializable):exact+any *, idx=4; #short !jvms: DecimalDigits::appendQuad @ bci:10 (line 491)
 902  StoreC  === 881 806 833 53  [[ ]]  @byte[int:>=0] (java/lang/Cloneable,java/io/Serializable):NotNull:exact+any *, idx=7; mismatched  Memory: @byte[int:>=0] (java/lang/Cloneable,java/io/Serializable):NotNull:exact+any *, idx=7;
[TraceMergeStores]: Replace
 851  StoreB  === 881 902 849 78  [[ 856 ]]  @byte[int:>=0] (java/lang/Cloneable,java/io/Serializable):NotNull:exact+any *, idx=7;  Memory: @byte[int:>=0] (java/lang/Cloneable,java/io/Serializable):NotNull:exact+any *, idx=7;
 856  StoreB  === 881 851 854 142  [[ 873 ]]  @byte[int:>=0] (java/lang/Cloneable,java/io/Serializable):NotNull:exact+any *, idx=7;  Memory: @byte[int:>=0] (java/lang/Cloneable,java/io/Serializable):NotNull:exact+any *, idx=7;
[TraceMergeStores]: with
  78  LoadS  === 5 7 76  [[ 142 533 615 865 851 515 303 649 689 903 ]]  @short[int:>=0] (java/lang/Cloneable,java/io/Serializable):exact+any *, idx=4; #short !jvms: DecimalDigits::appendQuad @ bci:22 (line 492)
 903  StoreC  === 881 902 849 78  [[ ]]  @byte[int:>=0] (java/lang/Cloneable,java/io/Serializable):NotNull:exact+any *, idx=7; mismatched  Memory: @byte[int:>=0] (java/lang/Cloneable,java/io/Serializable):NotNull:exact+any *, idx=7;


We can see there are two `SotreC` instructions here. Is it possible to merge these into OrI + StoreI, writing 4 bytes at a time?
@eme64 

In version 57ef68f4e49561423131287556cd592e29f05ba8, which uses JLA.appendLantin1, it can be optimized to OrI + StoreI.

-------------

PR Comment: https://git.openjdk.org/jdk/pull/26911#issuecomment-3530872741


More information about the core-libs-dev mailing list