This sub task of JDK-8356679 proposes implementation-only changes to sun.nio.cs.StreamEncoder. No API is changed. Implementation behavior is slightly changed w.r.t to self-calls to non-private methods, which should not be a risk, as StreamEncoder is final.
The target is to make the StreamEncoder::append(CharSequence) and StreamEncoder::append(CharSequence, int, int) methods *in the non-String* case be as efficient as they are already *in the String* case.
This is achived by now handling CharSequence in *the exact same* optimized way as String was specifically handled before. This generalization of the previously String-specific optimization is possible since Java 25, thanks to the new CharSequence::getChars(int, int, char[], int) bulk-read method.
Prior to the proposed change, the code was unefficient, as ontop of what the String-case did, the text content of other CharSequences (like StringBuilder and CharBuffer) had to be copied *once or multiply*, before it was finally processed *as* a String.
The changes in detail are:
* Extract the original implementation of StreamEncoder::write(String, int, int) to become a newly introduced, internal method StreamEncoder::implWrite(CharSequence, int, int). This allows making use of that exact original implementation by other methods, particularly StreamEncoder::append.
* StringEncoder::append(CharSequence) prevents the previously implied creation of an intermediate String representation in the non-String case (which implied creating another temporary object on the heap, and duplicating full text content), ontop of what the String case did.
* StringEncoder::append(CharSequence, int, int), in addition to the optimization of the single-arg case, also prevents the previously implied creation of a sub sequence for non-CharBuffer cases (which always meant to create another temporary object on the heap, and in many cases meant to duplicate partial text content). The CharBuffer-case exemption is preserved to still make use of its existing fast-path, as CharBuffers do not create temporary copies on subsequence(int, int) calls.
* As a side optimization, StringEncoder::write and StringEncode::apend prevent the creation of temporary ZERO-size buffers, effectively turning these methods into more or less no-ops.
The target is to make the StreamEncoder::append(CharSequence) and StreamEncoder::append(CharSequence, int, int) methods *in the non-String* case be as efficient as they are already *in the String* case.
This is achived by now handling CharSequence in *the exact same* optimized way as String was specifically handled before. This generalization of the previously String-specific optimization is possible since Java 25, thanks to the new CharSequence::getChars(int, int, char[], int) bulk-read method.
Prior to the proposed change, the code was unefficient, as ontop of what the String-case did, the text content of other CharSequences (like StringBuilder and CharBuffer) had to be copied *once or multiply*, before it was finally processed *as* a String.
The changes in detail are:
* Extract the original implementation of StreamEncoder::write(String, int, int) to become a newly introduced, internal method StreamEncoder::implWrite(CharSequence, int, int). This allows making use of that exact original implementation by other methods, particularly StreamEncoder::append.
* StringEncoder::append(CharSequence) prevents the previously implied creation of an intermediate String representation in the non-String case (which implied creating another temporary object on the heap, and duplicating full text content), ontop of what the String case did.
* StringEncoder::append(CharSequence, int, int), in addition to the optimization of the single-arg case, also prevents the previously implied creation of a sub sequence for non-CharBuffer cases (which always meant to create another temporary object on the heap, and in many cases meant to duplicate partial text content). The CharBuffer-case exemption is preserved to still make use of its existing fast-path, as CharBuffers do not create temporary copies on subsequence(int, int) calls.
* As a side optimization, StringEncoder::write and StringEncode::apend prevent the creation of temporary ZERO-size buffers, effectively turning these methods into more or less no-ops.