Skip to content

Commit

Permalink
Avoid allocating iterators when calling Message.Builder.addAllFoo(Ran…
Browse files Browse the repository at this point in the history
…domAccess List)

I've tried to keep the hot part of the loop (not null) in the loop without
requiring an extra function call, and only extracted the cold part (null
handling) to avoid repetition.

PiperOrigin-RevId: 670760103
  • Loading branch information
mhansen authored and copybara-github committed Sep 4, 2024
1 parent f44ad0b commit bd1887e
Showing 1 changed file with 26 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.RandomAccess;

/**
* A partial implementation of the {@link MessageLite} interface which implements as many methods of
Expand Down Expand Up @@ -343,19 +344,36 @@ private static <T> void addAllCheckingNulls(Iterable<T> values, List<? super T>
((ArrayList<T>) list).ensureCapacity(list.size() + ((Collection<T>) values).size());
}
int begin = list.size();
for (T value : values) {
if (value == null) {
// encountered a null value so we must undo our modifications prior to throwing
String message = "Element at index " + (list.size() - begin) + " is null.";
for (int i = list.size() - 1; i >= begin; i--) {
list.remove(i);
if (values instanceof List && values instanceof RandomAccess) {
List<T> valuesList = (List<T>) values;
int n = valuesList.size();
// Optimisation: avoid allocating Iterator for RandomAccess lists.
for (int i = 0; i < n; i++) {
T value = valuesList.get(i);
if (value == null) {
resetListAndThrow(list, begin);
}
list.add(value);
}
} else {
for (T value : values) {
if (value == null) {
resetListAndThrow(list, begin);
}
throw new NullPointerException(message);
list.add(value);
}
list.add(value);
}
}

/** Remove elements after index begin from the List and throw NullPointerException. */
private static void resetListAndThrow(List<?> list, int begin) {
String message = "Element at index " + (list.size() - begin) + " is null.";
for (int i = list.size() - 1; i >= begin; i--) {
list.remove(i);
}
throw new NullPointerException(message);
}

/** Construct an UninitializedMessageException reporting missing fields in the given message. */
protected static UninitializedMessageException newUninitializedMessageException(
MessageLite message) {
Expand Down

0 comments on commit bd1887e

Please sign in to comment.