From 21cd8675b9ae92727ec28ef45744f7923710f11e Mon Sep 17 00:00:00 2001 From: austnwil Date: Wed, 1 Oct 2025 15:08:59 -0700 Subject: [PATCH 1/5] Remove unnecessary array scans when cloning symbols into IonValueLite --- .../amazon/ion/impl/lite/IonSystemLite.java | 17 +------------- .../amazon/ion/impl/lite/IonValueLite.java | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/amazon/ion/impl/lite/IonSystemLite.java b/src/main/java/com/amazon/ion/impl/lite/IonSystemLite.java index 3eeeba1973..c694813120 100644 --- a/src/main/java/com/amazon/ion/impl/lite/IonSystemLite.java +++ b/src/main/java/com/amazon/ion/impl/lite/IonSystemLite.java @@ -749,11 +749,6 @@ private boolean cloneFieldNameIfAny(IonValueLite value) { return false; } SymbolToken token = reader.getFieldNameSymbol(); - String text = token.getText(); - if (text != null && token.getSid() != UNKNOWN_SYMBOL_ID) - { - token = newSymbolToken(text, UNKNOWN_SYMBOL_ID); - } value.setFieldNameSymbol(token); return true; } @@ -767,17 +762,7 @@ private boolean cloneAnnotationsIfAny(IonValueLite value) { if (annotations.length == 0) { return false; } - - for (int i = 0; i < annotations.length; i++) - { - SymbolToken token = annotations[i]; - String text = token.getText(); - if (text != null && token.getSid() != UNKNOWN_SYMBOL_ID ) - { - annotations[i] = newSymbolToken(text, UNKNOWN_SYMBOL_ID); - } - } - value.setTypeAnnotationSymbols(annotations); + value.setTypeAnnotationSymbolsNoCopy(annotations); return true; } diff --git a/src/main/java/com/amazon/ion/impl/lite/IonValueLite.java b/src/main/java/com/amazon/ion/impl/lite/IonValueLite.java index 08fd6661fa..9072ac2ef1 100644 --- a/src/main/java/com/amazon/ion/impl/lite/IonValueLite.java +++ b/src/main/java/com/amazon/ion/impl/lite/IonValueLite.java @@ -864,6 +864,8 @@ public final SymbolToken[] getTypeAnnotationSymbols(SymbolTableProvider symbolTa for (int i = 0; i < _annotations.length; i++) { if (_annotations[i] != null) { count++; + } else { + break; } } } @@ -925,6 +927,26 @@ public void setTypeAnnotationSymbols(SymbolToken... annotations) } } + // Sets type annotations for this value, assuming modifications to passed array + // are safe and the array will not be modified after call to this method. + // Prevents an unnecessary array copy if the array being passed in is newly-created + // for the call to this method. + protected void setTypeAnnotationSymbolsNoCopy(SymbolToken... annotations) + { + checkForLock(); + + if (annotations == null || annotations.length == 0) + { + // Normalize all empty lists to the same instance. + _annotations = SymbolToken.EMPTY_ARRAY; + } + else + { + _annotations = annotations; + checkAnnotationsForSids(); + } + } + public final String[] getTypeAnnotations() { // first we have to count the number of non-null From 06699e0ba7fe1bc9f63da3a32085ca29446ecef6 Mon Sep 17 00:00:00 2001 From: austnwil Date: Mon, 6 Oct 2025 14:04:51 -0700 Subject: [PATCH 2/5] Remove incorrect null check --- src/main/java/com/amazon/ion/impl/lite/IonValueLite.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/amazon/ion/impl/lite/IonValueLite.java b/src/main/java/com/amazon/ion/impl/lite/IonValueLite.java index 9072ac2ef1..146826371b 100644 --- a/src/main/java/com/amazon/ion/impl/lite/IonValueLite.java +++ b/src/main/java/com/amazon/ion/impl/lite/IonValueLite.java @@ -864,8 +864,6 @@ public final SymbolToken[] getTypeAnnotationSymbols(SymbolTableProvider symbolTa for (int i = 0; i < _annotations.length; i++) { if (_annotations[i] != null) { count++; - } else { - break; } } } From 49ad5355538ecb9606c31c2bc29c459a3bf72059 Mon Sep 17 00:00:00 2001 From: austnwil Date: Mon, 6 Oct 2025 16:57:44 -0700 Subject: [PATCH 3/5] Add back early break from annotations array on null --- src/main/java/com/amazon/ion/impl/lite/IonValueLite.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/amazon/ion/impl/lite/IonValueLite.java b/src/main/java/com/amazon/ion/impl/lite/IonValueLite.java index 146826371b..622a3622cf 100644 --- a/src/main/java/com/amazon/ion/impl/lite/IonValueLite.java +++ b/src/main/java/com/amazon/ion/impl/lite/IonValueLite.java @@ -864,6 +864,10 @@ public final SymbolToken[] getTypeAnnotationSymbols(SymbolTableProvider symbolTa for (int i = 0; i < _annotations.length; i++) { if (_annotations[i] != null) { count++; + } else { + // null indicates the end of the array. + // This assumption is also present in IonValueLite(IonValueLite existing, IonContext context) constructor. + break; } } } From 286c0a1f5403e6f2e050a91bf1b25156ed660912 Mon Sep 17 00:00:00 2001 From: austnwil Date: Fri, 10 Oct 2025 12:11:56 -0700 Subject: [PATCH 4/5] Document that IonReader.getTypeAnnotationSymbols() returns fresh array --- src/main/java/com/amazon/ion/IonReader.java | 3 +++ src/main/java/com/amazon/ion/IonValue.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/main/java/com/amazon/ion/IonReader.java b/src/main/java/com/amazon/ion/IonReader.java index fb572fadc8..9defb8ef76 100644 --- a/src/main/java/com/amazon/ion/IonReader.java +++ b/src/main/java/com/amazon/ion/IonReader.java @@ -252,6 +252,9 @@ public interface IonReader /** * Gets the current value's annotations as symbol tokens (text + ID). + * Implementations are guaranteed to return a new array that is safe + * for the caller to modify if the array length is greater than 0. + * Zero-length arrays returned here are not safe to modify. * * @return the (ordered) annotations on the current value, or an empty * array (not {@code null}) if there are none. diff --git a/src/main/java/com/amazon/ion/IonValue.java b/src/main/java/com/amazon/ion/IonValue.java index db65ffd687..e503f344bd 100644 --- a/src/main/java/com/amazon/ion/IonValue.java +++ b/src/main/java/com/amazon/ion/IonValue.java @@ -310,6 +310,9 @@ public interface IonValue /** * Gets this value's user type annotations as interned symbols (text + ID). + * Implementations are guaranteed to return a new array that is safe for + * the caller to modify if the array length is greater than 0. Zero-length + * arrays returned here are not safe to modify. * * @return the (ordered) annotations on the current value, or an empty * array (not {@code null}) if there are none. From e7010acb7c223725004eb8687a04cff7aa0e46f6 Mon Sep 17 00:00:00 2001 From: austnwil Date: Fri, 10 Oct 2025 12:39:24 -0700 Subject: [PATCH 5/5] Remove unnecessary zero-length caveat from doc --- src/main/java/com/amazon/ion/IonReader.java | 3 +-- src/main/java/com/amazon/ion/IonValue.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/amazon/ion/IonReader.java b/src/main/java/com/amazon/ion/IonReader.java index 9defb8ef76..ae0a0eb44e 100644 --- a/src/main/java/com/amazon/ion/IonReader.java +++ b/src/main/java/com/amazon/ion/IonReader.java @@ -253,8 +253,7 @@ public interface IonReader /** * Gets the current value's annotations as symbol tokens (text + ID). * Implementations are guaranteed to return a new array that is safe - * for the caller to modify if the array length is greater than 0. - * Zero-length arrays returned here are not safe to modify. + * for the caller to modify. * * @return the (ordered) annotations on the current value, or an empty * array (not {@code null}) if there are none. diff --git a/src/main/java/com/amazon/ion/IonValue.java b/src/main/java/com/amazon/ion/IonValue.java index e503f344bd..8e738d5e97 100644 --- a/src/main/java/com/amazon/ion/IonValue.java +++ b/src/main/java/com/amazon/ion/IonValue.java @@ -311,8 +311,7 @@ public interface IonValue /** * Gets this value's user type annotations as interned symbols (text + ID). * Implementations are guaranteed to return a new array that is safe for - * the caller to modify if the array length is greater than 0. Zero-length - * arrays returned here are not safe to modify. + * the caller to modify. * * @return the (ordered) annotations on the current value, or an empty * array (not {@code null}) if there are none.