From b8c0a68d06957a9ed5d76feae9ab659ad104908a Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Sat, 7 Jun 2025 16:15:37 +0200 Subject: [PATCH] Replace streams with indexed for-loops. --- .../hosted/HostedLayeredModuleSingleton.java | 5 +- .../SharedLayerBootLayerModulesSingleton.java | 5 +- .../code/RuntimeMetadataEncoderImpl.java | 7 +- .../hosted/imagelayer/CapnProtoAdapters.java | 291 ++++++++++++++++++ .../imagelayer/SVMImageLayerLoader.java | 123 ++------ .../SVMImageLayerSingletonLoader.java | 11 +- .../hosted/jdk/JNIRegistrationSupport.java | 4 +- 7 files changed, 327 insertions(+), 119 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/CapnProtoAdapters.java diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedLayeredModuleSingleton.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedLayeredModuleSingleton.java index 77369412becc..38326f8d48b9 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedLayeredModuleSingleton.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedLayeredModuleSingleton.java @@ -29,7 +29,6 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; import com.oracle.svm.core.imagelayer.BuildingInitialLayerPredicate; @@ -37,7 +36,7 @@ import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; -import com.oracle.svm.hosted.imagelayer.SVMImageLayerLoader; +import com.oracle.svm.hosted.imagelayer.CapnProtoAdapters; import com.oracle.svm.hosted.imagelayer.SVMImageLayerSingletonLoader; import com.oracle.svm.hosted.imagelayer.SVMImageLayerWriter; import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.ModulePackages; @@ -103,7 +102,7 @@ private static Map>> getModulePackages(StructLis Map> packages = new HashMap<>(); for (int j = 0; j < packagesReader.size(); ++j) { var packageEntryReader = packagesReader.get(j); - HashSet modules = SVMImageLayerLoader.streamStrings(packageEntryReader.getModules()).collect(Collectors.toCollection(HashSet::new)); + Set modules = CapnProtoAdapters.toCollection(packageEntryReader.getModules(), HashSet::new); packages.put(packageEntryReader.getPackageKey().toString(), modules); } modulePackages.put(entryReader.getModuleKey().toString(), packages); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SharedLayerBootLayerModulesSingleton.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SharedLayerBootLayerModulesSingleton.java index 3694da7beb61..8f90e72bd556 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SharedLayerBootLayerModulesSingleton.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SharedLayerBootLayerModulesSingleton.java @@ -24,11 +24,13 @@ */ package com.oracle.svm.hosted; +import java.util.ArrayList; import java.util.Collection; import java.util.EnumSet; import java.util.List; import java.util.stream.Stream; +import com.oracle.svm.hosted.imagelayer.CapnProtoAdapters; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -39,7 +41,6 @@ import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; -import com.oracle.svm.hosted.imagelayer.SVMImageLayerLoader; import com.oracle.svm.hosted.imagelayer.SVMImageLayerSingletonLoader; import com.oracle.svm.hosted.imagelayer.SVMImageLayerWriter; @@ -91,7 +92,7 @@ public PersistFlags preparePersist(ImageSingletonWriter writer) { @SuppressWarnings("unused") public static Object createFromLoader(ImageSingletonLoader loader) { SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl loaderImpl = (SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl) loader; - List moduleNames = SVMImageLayerLoader.streamStrings(loaderImpl.getSnapshotReader().getSharedLayerBootLayerModules()).toList(); + List moduleNames = CapnProtoAdapters.toCollection(loaderImpl.getSnapshotReader().getSharedLayerBootLayerModules(), ArrayList::new); return new SharedLayerBootLayerModulesSingleton(moduleNames); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/RuntimeMetadataEncoderImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/RuntimeMetadataEncoderImpl.java index 5bac4df34725..1beb3da2ff24 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/RuntimeMetadataEncoderImpl.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/RuntimeMetadataEncoderImpl.java @@ -66,8 +66,8 @@ import java.util.TreeSet; import java.util.function.BiConsumer; import java.util.function.Consumer; -import java.util.stream.Collectors; +import com.oracle.svm.hosted.imagelayer.CapnProtoAdapters; import org.graalvm.collections.Pair; import org.graalvm.nativeimage.AnnotationAccess; import org.graalvm.nativeimage.ImageSingletons; @@ -104,7 +104,6 @@ import com.oracle.svm.hosted.annotation.TypeAnnotationValue; import com.oracle.svm.hosted.image.NativeImageCodeCache.ReflectionMetadataEncoderFactory; import com.oracle.svm.hosted.image.NativeImageCodeCache.RuntimeMetadataEncoder; -import com.oracle.svm.hosted.imagelayer.SVMImageLayerLoader; import com.oracle.svm.hosted.imagelayer.SVMImageLayerSingletonLoader; import com.oracle.svm.hosted.imagelayer.SVMImageLayerWriter; import com.oracle.svm.hosted.meta.HostedField; @@ -1312,8 +1311,8 @@ public static Object createFromLoader(ImageSingletonLoader loader) { SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl loaderImpl = (SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl) loader; var reader = loaderImpl.getSnapshotReader().getLayeredRuntimeMetadataSingleton(); - Set registeredMethods = SVMImageLayerLoader.streamInts(reader.getMethods()).boxed().collect(Collectors.toCollection(HashSet::new)); - Set registeredFields = SVMImageLayerLoader.streamInts(reader.getFields()).boxed().collect(Collectors.toCollection(HashSet::new)); + Set registeredMethods = CapnProtoAdapters.toCollection(reader.getMethods(), Integer::valueOf, HashSet::new); + Set registeredFields = CapnProtoAdapters.toCollection(reader.getFields(), Integer::valueOf, HashSet::new); return new LayeredRuntimeMetadataSingleton(registeredMethods, registeredFields); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/CapnProtoAdapters.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/CapnProtoAdapters.java new file mode 100644 index 000000000000..c2c3edb6af34 --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/CapnProtoAdapters.java @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.hosted.imagelayer; + +import java.util.Collection; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.IntConsumer; +import java.util.function.IntFunction; +import java.util.function.Supplier; +import java.util.function.ToIntFunction; + +import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PrimitiveArray; +import com.oracle.svm.shaded.org.capnproto.PrimitiveList; +import com.oracle.svm.shaded.org.capnproto.StructList; +import com.oracle.svm.shaded.org.capnproto.StructReader; +import com.oracle.svm.shaded.org.capnproto.TextList; + +/** + * Collection of adapters to interact with the Cap'n Proto internal value representation. + */ +public class CapnProtoAdapters { + /** + * Iterate values from a {@link com.oracle.svm.shaded.org.capnproto.PrimitiveList.Int} reader + * and pass them to the action. + */ + static void forEach(PrimitiveList.Int.Reader reader, IntConsumer action) { + for (int i = 0; i < reader.size(); i++) { + action.accept(reader.get(i)); + } + } + + /** + * Iterate values from a {@link com.oracle.svm.shaded.org.capnproto.TextList} reader and pass + * them to the action. + */ + public static void forEach(TextList.Reader reader, Consumer action) { + for (int i = 0; i < reader.size(); i++) { + action.accept(reader.get(i).toString()); + } + } + + /** + * Iterate values from a {@link com.oracle.svm.shaded.org.capnproto.PrimitiveList.Int} reader, + * apply the mapping function, then store them in the supplied array at the same index. + */ + static T[] toArray(PrimitiveList.Int.Reader reader, IntFunction mapper, IntFunction arrayGenerator) { + T[] array = arrayGenerator.apply(reader.size()); + for (int i = 0; i < reader.size(); i++) { + array[i] = mapper.apply(reader.get(i)); + } + return array; + } + + /** + * Iterate values from a {@link com.oracle.svm.shaded.org.capnproto.StructList} reader, apply + * the mapping function, then store them in the supplied array at the same index. + */ + static T[] toArray(StructList.Reader reader, Function mapper, IntFunction arrayGenerator) { + T[] array = arrayGenerator.apply(reader.size()); + for (int i = 0; i < reader.size(); i++) { + array[i] = mapper.apply(reader.get(i)); + } + return array; + } + + /** + * Iterate values from a {@link com.oracle.svm.shaded.org.capnproto.TextList} reader, convert + * them to {@link String}, apply the mapping function, then store them in the supplied array at + * the same index. + */ + static T[] toArray(TextList.Reader reader, Function mapper, IntFunction arrayGenerator) { + T[] array = arrayGenerator.apply(reader.size()); + for (int i = 0; i < reader.size(); i++) { + array[i] = mapper.apply(reader.get(i).toString()); + } + return array; + } + + /** + * Iterate values from a {@link com.oracle.svm.shaded.org.capnproto.PrimitiveList.Int} reader, + * apply the mapping function, then collect them in the supplied collection. + */ + public static > U toCollection(PrimitiveList.Int.Reader reader, IntFunction mapper, Supplier collectionFactory) { + U collection = collectionFactory.get(); + for (int i = 0; i < reader.size(); i++) { + collection.add(mapper.apply(reader.get(i))); + } + return collection; + } + + /** + * Iterate values from a {@link com.oracle.svm.shaded.org.capnproto.TextList} reader, convert + * them to {@link String}, then collect them in the supplied collection. + */ + public static > U toCollection(TextList.Reader reader, Supplier collectionFactory) { + return toCollection(reader, (s) -> s, collectionFactory); + } + + /** + * Iterate values from a {@link com.oracle.svm.shaded.org.capnproto.TextList} reader, convert + * them to {@link String}, apply the mapping function, then collect them in the supplied + * collection. + */ + public static > U toCollection(TextList.Reader reader, Function mapper, Supplier collectionFactory) { + U collection = collectionFactory.get(); + for (int i = 0; i < reader.size(); i++) { + collection.add(mapper.apply(reader.get(i).toString())); + } + return collection; + } + + /** + * Extract values from a {@link PrimitiveArray} reader to the corresponding Java primitive + * array. + */ + static Object toArray(PrimitiveArray.Reader reader) { + return switch (reader.which()) { + case Z -> toBooleanArray(reader.getZ()); + case B -> toByteArray(reader.getB()); + case S -> toShortArray(reader.getS()); + case C -> toCharArray(reader.getC()); + case I -> toIntArray(reader.getI()); + case F -> toFloatArray(reader.getF()); + case J -> toLongArray(reader.getJ()); + case D -> toDoubleArray(reader.getD()); + case _NOT_IN_SCHEMA -> throw new IllegalArgumentException("Unsupported kind: " + reader.which()); + }; + } + + /** + * Extract values from a {@link com.oracle.svm.shaded.org.capnproto.PrimitiveList.Boolean} + * reader to a {@code boolean[]} array. + */ + protected static boolean[] toBooleanArray(PrimitiveList.Boolean.Reader booleanReader) { + boolean[] booleanArray = new boolean[booleanReader.size()]; + for (int i = 0; i < booleanReader.size(); i++) { + booleanArray[i] = booleanReader.get(i); + } + return booleanArray; + } + + /** + * Extract values from a {@link com.oracle.svm.shaded.org.capnproto.PrimitiveList.Byte} reader + * to a {@code byte[]} array. + */ + static byte[] toByteArray(PrimitiveList.Byte.Reader byteReader) { + byte[] byteArray = new byte[byteReader.size()]; + for (int i = 0; i < byteReader.size(); i++) { + byteArray[i] = byteReader.get(i); + } + return byteArray; + } + + /** + * Extract values from a {@link com.oracle.svm.shaded.org.capnproto.PrimitiveList.Short} reader + * to a {@code short[]} array. + */ + static short[] toShortArray(PrimitiveList.Short.Reader shortReader) { + short[] shortArray = new short[shortReader.size()]; + for (int i = 0; i < shortReader.size(); i++) { + shortArray[i] = shortReader.get(i); + } + return shortArray; + } + + /** + * Extract values from a {@link com.oracle.svm.shaded.org.capnproto.PrimitiveList.Short} reader + * to a {@code char[]} array. + */ + static char[] toCharArray(PrimitiveList.Short.Reader charReader) { + char[] charArray = new char[charReader.size()]; + for (int i = 0; i < charReader.size(); i++) { + charArray[i] = (char) charReader.get(i); + } + return charArray; + } + + /** + * Extract values from a {@link com.oracle.svm.shaded.org.capnproto.PrimitiveList.Int} reader to + * a {@code int[]} array. + */ + public static int[] toIntArray(PrimitiveList.Int.Reader intReader) { + int[] intArray = new int[intReader.size()]; + for (int i = 0; i < intReader.size(); i++) { + intArray[i] = intReader.get(i); + } + return intArray; + } + + /** + * Extract values from a {@link com.oracle.svm.shaded.org.capnproto.PrimitiveList.Float} reader + * to a {@code float[]} array. + */ + static float[] toFloatArray(PrimitiveList.Float.Reader floatReader) { + float[] floatArray = new float[floatReader.size()]; + for (int i = 0; i < floatReader.size(); i++) { + floatArray[i] = floatReader.get(i); + } + return floatArray; + } + + /** + * Extract values from a {@link com.oracle.svm.shaded.org.capnproto.PrimitiveList.Long} reader + * to a {@code long[]} array. + */ + static long[] toLongArray(PrimitiveList.Long.Reader longReader) { + long[] longArray = new long[longReader.size()]; + for (int i = 0; i < longReader.size(); i++) { + longArray[i] = longReader.get(i); + } + return longArray; + } + + /** + * Extract values from a {@link com.oracle.svm.shaded.org.capnproto.PrimitiveList.Double} reader + * to a {@code double[]} array. + */ + static double[] toDoubleArray(PrimitiveList.Double.Reader doubleReader) { + double[] doubleArray = new double[doubleReader.size()]; + for (int i = 0; i < doubleReader.size(); i++) { + doubleArray[i] = doubleReader.get(i); + } + return doubleArray; + } + + /** + * Extract values from a {@link com.oracle.svm.shaded.org.capnproto.TextList} reader to a + * {@code String[]} array. + */ + public static String[] toStringArray(TextList.Reader reader) { + return toArray(reader, (s) -> s, String[]::new); + } + + /** + * Find the value containing the given {@code key} in a + * {@link com.oracle.svm.shaded.org.capnproto.StructList} reader, applying the + * {@code keyExtractor} to searched values. The input list should be sorted by the {@code key} + * and contain no duplicates. + * + * @return the found value or {@code null} + */ + static T binarySearchUnique(int key, StructList.Reader sortedList, ToIntFunction keyExtractor) { + int low = 0; + int high = sortedList.size() - 1; + + int prevMid = -1; + int prevKey = 0; + while (low <= high) { + int mid = (low + high) >>> 1; + T midStruct = sortedList.get(mid); + int midKey = keyExtractor.applyAsInt(midStruct); + + assert prevMid == -1 || (mid < prevMid && midKey < prevKey) || (mid > prevMid && midKey > prevKey) : "unsorted or contains duplicates"; + + if (midKey < key) { + low = mid + 1; + } else if (midKey > key) { + high = mid - 1; + } else { + return midStruct; + } + + prevMid = mid; + prevKey = midKey; + } + return null; + } +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java index bd519503f71d..6b12e65087dd 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java @@ -45,14 +45,10 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.IntFunction; import java.util.function.Supplier; -import java.util.function.ToIntFunction; import java.util.stream.IntStream; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; import org.graalvm.collections.EconomicMap; import org.graalvm.nativeimage.AnnotationAccess; @@ -113,7 +109,6 @@ import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PersistedConstant.Object.Relinking; import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PersistedConstant.Object.Relinking.EnumConstant; import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PersistedConstant.Object.Relinking.StringConstant; -import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PrimitiveArray; import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PrimitiveValue; import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.SharedLayerSnapshot; import com.oracle.svm.hosted.jni.JNIAccessFeature; @@ -123,12 +118,9 @@ import com.oracle.svm.hosted.reflect.ReflectionFeature; import com.oracle.svm.hosted.reflect.serialize.SerializationFeature; import com.oracle.svm.hosted.util.IdentityHashCodeUtil; -import com.oracle.svm.shaded.org.capnproto.ListReader; import com.oracle.svm.shaded.org.capnproto.PrimitiveList; import com.oracle.svm.shaded.org.capnproto.StructList; -import com.oracle.svm.shaded.org.capnproto.StructReader; import com.oracle.svm.shaded.org.capnproto.Text; -import com.oracle.svm.shaded.org.capnproto.TextList; import com.oracle.svm.util.LogUtils; import com.oracle.svm.util.ReflectionUtil; @@ -276,8 +268,7 @@ public void loadLayerAnalysis() { methodDescriptorToBaseLayerId.put(descriptor, methodData.getId()); } - streamInts(snapshot.getConstantsToRelink()).mapToObj(this::findConstant) - .forEach(c -> prepareConstantRelinking(c, c.getIdentityHashCode(), c.getId())); + CapnProtoAdapters.forEach(snapshot.getConstantsToRelink(), id -> prepareConstantRelinking(findConstant(id))); } /** @@ -325,49 +316,16 @@ private void relinkStaticFinalFieldValues(boolean isLateLoading) { }); } - public static IntStream streamInts(PrimitiveList.Int.Reader reader) { - return IntStream.range(0, reader.size()).map(reader::get); - } - - public static Stream streamStrings(TextList.Reader reader) { - return IntStream.range(0, reader.size()).mapToObj(i -> reader.get(i).toString()); - } - private PersistedConstant.Reader findConstant(int id) { - return binarySearchUnique(id, snapshot.getConstants(), PersistedConstant.Reader::getId); - } - - private static T binarySearchUnique(int key, StructList.Reader sortedList, ToIntFunction keyExtractor) { - int low = 0; - int high = sortedList.size() - 1; - - int prevMid = -1; - int prevKey = 0; - while (low <= high) { - int mid = (low + high) >>> 1; - T midStruct = sortedList.get(mid); - int midKey = keyExtractor.applyAsInt(midStruct); - - assert prevMid == -1 || (mid < prevMid && midKey < prevKey) || (mid > prevMid && midKey > prevKey) : "unsorted or contains duplicates"; - - if (midKey < key) { - low = mid + 1; - } else if (midKey > key) { - high = mid - 1; - } else { - return midStruct; - } - - prevMid = mid; - prevKey = midKey; - } - return null; + return CapnProtoAdapters.binarySearchUnique(id, snapshot.getConstants(), PersistedConstant.Reader::getId); } - private void prepareConstantRelinking(PersistedConstant.Reader constantData, int identityHashCode, int id) { + private void prepareConstantRelinking(PersistedConstant.Reader constantData) { if (!constantData.isObject()) { return; } + int id = constantData.getId(); + int identityHashCode = constantData.getIdentityHashCode(); Relinking.Reader relinking = constantData.getObject().getRelinking(); if (relinking.isClassConstant()) { @@ -408,7 +366,7 @@ public AnalysisType getAnalysisTypeForBaseLayerId(int tid) { } private PersistedAnalysisType.Reader findType(int tid) { - return binarySearchUnique(tid, snapshot.getTypes(), PersistedAnalysisType.Reader::getId); + return CapnProtoAdapters.binarySearchUnique(tid, snapshot.getTypes(), PersistedAnalysisType.Reader::getId); } /** @@ -435,8 +393,7 @@ private void loadType(PersistedAnalysisType.Reader typeData) { Class clazz = lookupBaseLayerTypeInHostVM(typeData.getClassJavaName().toString()); ResolvedJavaType superClass = getResolvedJavaTypeForBaseLayerId(typeData.getSuperClassTypeId()); - ResolvedJavaType[] interfaces = streamInts(typeData.getInterfaces()) - .mapToObj(this::getResolvedJavaTypeForBaseLayerId).toArray(ResolvedJavaType[]::new); + ResolvedJavaType[] interfaces = CapnProtoAdapters.toArray(typeData.getInterfaces(), this::getResolvedJavaTypeForBaseLayerId, ResolvedJavaType[]::new); if (clazz != null) { /* Lookup the host VM type and create the analysis type. */ @@ -450,10 +407,8 @@ private void loadType(PersistedAnalysisType.Reader typeData) { */ BaseLayerType baseLayerType = getBaseLayerType(typeData, tid, superClass, interfaces); - baseLayerType.setInstanceFields(streamInts(typeData.getInstanceFieldIds()) - .mapToObj(this::getBaseLayerField).toArray(ResolvedJavaField[]::new)); - baseLayerType.setInstanceFieldsWithSuper(streamInts(typeData.getInstanceFieldIdsWithSuper()) - .mapToObj(this::getBaseLayerField).toArray(ResolvedJavaField[]::new)); + baseLayerType.setInstanceFields(CapnProtoAdapters.toArray(typeData.getInstanceFieldIds(), this::getBaseLayerField, ResolvedJavaField[]::new)); + baseLayerType.setInstanceFieldsWithSuper(CapnProtoAdapters.toArray(typeData.getInstanceFieldIdsWithSuper(), this::getBaseLayerField, ResolvedJavaField[]::new)); AnalysisType type = universe.lookup(baseLayerType); guarantee(getBaseLayerTypeId(type) == tid, "The base layer type %s is not correctly matched to the id %d", type, tid); @@ -484,8 +439,7 @@ protected boolean delegateLoadType(PersistedAnalysisType.Reader typeData) { loadLambdaTypes(capturingClass); return types.containsKey(typeData.getId()); } else if (wrappedType.isProxyType()) { - Class[] interfaces = Stream.of(typeData.getInterfaces()).flatMapToInt(r -> IntStream.range(0, r.size()).map(r::get)) - .mapToObj(i -> getAnalysisTypeForBaseLayerId(i).getJavaClass()).toArray(Class[]::new); + Class[] interfaces = CapnProtoAdapters.toArray(typeData.getInterfaces(), tid -> getAnalysisTypeForBaseLayerId(tid).getJavaClass(), Class[]::new); /* GR-59854: The deprecation warning comes from this call to Proxy.getProxyClass. */ Class proxy = Proxy.getProxyClass(interfaces[0].getClassLoader(), interfaces); metaAccess.lookupJavaType(proxy); @@ -602,7 +556,8 @@ private static Class lookupPrimitiveClass(String type) { private BaseLayerType getBaseLayerType(int tid) { PersistedAnalysisType.Reader typeData = findType(tid); ResolvedJavaType superClass = getResolvedJavaTypeForBaseLayerId(typeData.getSuperClassTypeId()); - ResolvedJavaType[] interfaces = streamInts(typeData.getInterfaces()).mapToObj(this::getResolvedJavaTypeForBaseLayerId).toArray(ResolvedJavaType[]::new); + + ResolvedJavaType[] interfaces = CapnProtoAdapters.toArray(typeData.getInterfaces(), this::getResolvedJavaTypeForBaseLayerId, ResolvedJavaType[]::new); return getBaseLayerType(typeData, tid, superClass, interfaces); } @@ -621,7 +576,7 @@ private BaseLayerType getBaseLayerType(PersistedAnalysisType.Reader td, int tid, } private Annotation[] getAnnotations(StructList.Reader reader) { - return IntStream.range(0, reader.size()).mapToObj(reader::get).map(this::getAnnotation).toArray(Annotation[]::new); + return CapnProtoAdapters.toArray(reader, this::getAnnotation, Annotation[]::new); } private Annotation getAnnotation(SharedLayerSnapshotCapnProtoSchemaHolder.Annotation.Reader a) { @@ -655,7 +610,7 @@ yield switch (JavaKind.fromPrimitiveOrVoidTypeChar(typeChar)) { default -> throw AnalysisError.shouldNotReachHere("Unknown annotation value type: " + typeChar); }; } - case PRIMITIVE_ARRAY -> getArray(v.getPrimitiveArray()); + case PRIMITIVE_ARRAY -> CapnProtoAdapters.toArray(v.getPrimitiveArray()); case CLASS_NAME -> imageLayerBuildingSupport.lookupClass(false, v.getClassName().toString()); case ANNOTATION -> getAnnotation(v.getAnnotation()); case MEMBERS -> { @@ -780,7 +735,7 @@ public AnalysisMethod getAnalysisMethodForBaseLayerId(int mid) { } private PersistedAnalysisMethod.Reader findMethod(int mid) { - return binarySearchUnique(mid, snapshot.getMethods(), PersistedAnalysisMethod.Reader::getId); + return CapnProtoAdapters.binarySearchUnique(mid, snapshot.getMethods(), PersistedAnalysisMethod.Reader::getId); } private void loadMethod(PersistedAnalysisMethod.Reader methodData) { @@ -793,7 +748,7 @@ private void loadMethod(PersistedAnalysisMethod.Reader methodData) { int tid = methodData.getDeclaringTypeId(); AnalysisType type = getAnalysisTypeForBaseLayerId(tid); - AnalysisType[] parameterTypes = streamInts(methodData.getArgumentTypeIds()).mapToObj(this::getAnalysisTypeForBaseLayerId).toArray(AnalysisType[]::new); + AnalysisType[] parameterTypes = CapnProtoAdapters.toArray(methodData.getArgumentTypeIds(), this::getAnalysisTypeForBaseLayerId, AnalysisType[]::new); AnalysisType returnType = getAnalysisTypeForBaseLayerId(methodData.getReturnTypeId()); @@ -804,7 +759,7 @@ private void loadMethod(PersistedAnalysisMethod.Reader methodData) { Executable method = null; Class clazz = lookupBaseLayerTypeInHostVM(className); if (clazz != null) { - Class[] argumentClasses = streamStrings(methodData.getArgumentClassNames()).map(this::lookupBaseLayerTypeInHostVM).toArray(Class[]::new); + Class[] argumentClasses = CapnProtoAdapters.toArray(methodData.getArgumentClassNames(), this::lookupBaseLayerTypeInHostVM, Class[]::new); method = lookupMethodByReflection(name, clazz, argumentClasses); } @@ -826,7 +781,7 @@ private void loadMethod(PersistedAnalysisMethod.Reader methodData) { } } - ResolvedSignature signature = ResolvedSignature.fromList(Arrays.stream(parameterTypes).toList(), returnType); + ResolvedSignature signature = ResolvedSignature.fromArray(parameterTypes, returnType); if (name.equals(CONSTRUCTOR_NAME)) { type.findConstructor(signature); @@ -902,8 +857,7 @@ private Executable getWrappedMember(WrappedMethod.WrappedMember.Reader memberDat return null; } String name = memberData.getName().toString(); - Class[] parameters = StreamSupport.stream(memberData.getArgumentTypeNames().spliterator(), false).map(Text.Reader::toString) - .map(c -> imageLayerBuildingSupport.lookupClass(false, c)).toArray(Class[]::new); + Class[] parameters = CapnProtoAdapters.toArray(memberData.getArgumentTypeNames(), c -> imageLayerBuildingSupport.lookupClass(false, c), Class[]::new); return lookupMethodByReflection(name, declaringClass, parameters); } @@ -983,7 +937,7 @@ public StructList.Reader { - Object array = getArray(baseLayerConstant.getPrimitiveData()); + Object array = CapnProtoAdapters.toArray(baseLayerConstant.getPrimitiveData()); addBaseLayerObject(id, objectOffset, () -> new ImageHeapPrimitiveArray(type, null, array, Array.getLength(array), identityHashCode, id)); } case RELOCATABLE -> { @@ -1508,9 +1462,7 @@ private boolean delegateProcessing(ConstantReference.Reader constantRef, Object[ CEntryPointLiteralReference.Reader ref = constantRef.getCEntryPointLiteralCodePointer(); String methodName = ref.getMethodName().toString(); Class definingClass = lookupBaseLayerTypeInHostVM(ref.getDefiningClass().toString()); - Class[] parameterTypes = IntStream.range(0, ref.getParameterNames().size()) - .mapToObj(j -> ref.getParameterNames().get(j).toString()) - .map(this::lookupBaseLayerTypeInHostVM).toArray(Class[]::new); + Class[] parameterTypes = CapnProtoAdapters.toArray(ref.getParameterNames(), this::lookupBaseLayerTypeInHostVM, Class[]::new); values[i] = new PatchedWordConstant(new CEntryPointLiteralCodePointer(definingClass, methodName, parameterTypes), cEntryPointerLiteralPointerType); return true; } else if (constantRef.isCGlobalDataBasePointer()) { @@ -1522,35 +1474,6 @@ private boolean delegateProcessing(ConstantReference.Reader constantRef, Object[ return false; } - private static Object getArray(PrimitiveArray.Reader reader) { - return switch (reader.which()) { - case Z -> getBooleans(reader.getZ()); - case B -> toArray(reader.getB(), r -> IntStream.range(0, r.size()).collect(() -> new byte[r.size()], (a, i) -> a[i] = r.get(i), combineUnsupported())); - case S -> toArray(reader.getS(), r -> IntStream.range(0, r.size()).collect(() -> new short[r.size()], (a, i) -> a[i] = r.get(i), combineUnsupported())); - case C -> toArray(reader.getC(), r -> IntStream.range(0, r.size()).collect(() -> new char[r.size()], (a, i) -> a[i] = (char) r.get(i), combineUnsupported())); - case I -> toArray(reader.getI(), r -> IntStream.range(0, r.size()).collect(() -> new int[r.size()], (a, i) -> a[i] = r.get(i), combineUnsupported())); - case F -> toArray(reader.getF(), r -> IntStream.range(0, r.size()).collect(() -> new float[r.size()], (a, i) -> a[i] = r.get(i), combineUnsupported())); - case J -> toArray(reader.getJ(), r -> IntStream.range(0, r.size()).collect(() -> new long[r.size()], (a, i) -> a[i] = r.get(i), combineUnsupported())); - case D -> toArray(reader.getD(), r -> IntStream.range(0, r.size()).collect(() -> new double[r.size()], (a, i) -> a[i] = r.get(i), combineUnsupported())); - case _NOT_IN_SCHEMA -> throw new IllegalArgumentException("Unsupported kind: " + reader.which()); - }; - } - - protected static boolean[] getBooleans(PrimitiveList.Boolean.Reader r) { - return IntStream.range(0, r.size()).collect(() -> new boolean[r.size()], (a, i) -> a[i] = r.get(i), combineUnsupported()); - } - - /** Enables concise one-liners without explicit types in {@link #getArray}. */ - private static A toArray(T reader, Function fun) { - return fun.apply(reader); - } - - private static BiConsumer combineUnsupported() { - return (u, v) -> { - throw new UnsupportedOperationException("Combining partial results not supported, streams must be sequential"); - }; - } - /** * For a parent constant return the referenced field-position or array-element-index value * corresponding to index. diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerSingletonLoader.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerSingletonLoader.java index 2677e0ce4d8b..ace26daf0bf9 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerSingletonLoader.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerSingletonLoader.java @@ -24,8 +24,6 @@ */ package com.oracle.svm.hosted.imagelayer; -import static com.oracle.svm.hosted.imagelayer.SVMImageLayerLoader.getBooleans; - import java.lang.reflect.Method; import java.util.HashMap; import java.util.HashSet; @@ -33,10 +31,7 @@ import java.util.Map; import java.util.Set; import java.util.stream.IntStream; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; -import com.oracle.svm.shaded.org.capnproto.Text; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.UnmodifiableEconomicMap; @@ -75,9 +70,9 @@ public Map>> loadImageSingletons(Object forbiddenObject) { case I -> v.getI(); case J -> v.getJ(); case STR -> v.getStr().toString(); - case IL -> Stream.of(v.getIl()).flatMapToInt(r -> IntStream.range(0, r.size()).map(r::get)).toArray(); - case ZL -> getBooleans(v.getZl()); - case STRL -> StreamSupport.stream(v.getStrl().spliterator(), false).map(Text.Reader::toString).toArray(String[]::new); + case IL -> CapnProtoAdapters.toIntArray(v.getIl()); + case ZL -> CapnProtoAdapters.toBooleanArray(v.getZl()); + case STRL -> CapnProtoAdapters.toStringArray(v.getStrl()); case _NOT_IN_SCHEMA -> throw new IllegalStateException("Unexpected value: " + v.which()); }; keyStore.put(entry.getKey().toString(), value); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationSupport.java index b7ba36080d23..2224bb83b77b 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationSupport.java @@ -42,6 +42,7 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.stream.Stream; +import com.oracle.svm.hosted.imagelayer.CapnProtoAdapters; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.impl.InternalPlatform; @@ -67,7 +68,6 @@ import com.oracle.svm.hosted.c.NativeLibraries; import com.oracle.svm.hosted.c.codegen.CCompilerInvoker; import com.oracle.svm.hosted.c.util.FileUtils; -import com.oracle.svm.hosted.imagelayer.SVMImageLayerLoader; import com.oracle.svm.hosted.imagelayer.SVMImageLayerSingletonLoader; import com.oracle.svm.hosted.imagelayer.SVMImageLayerWriter; @@ -394,7 +394,7 @@ public PersistFlags preparePersist(ImageSingletonWriter writer) { public static Object createFromLoader(ImageSingletonLoader loader) { JNIRegistrationSupportSingleton singleton = new JNIRegistrationSupportSingleton(); var snapshotReader = ((SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl) loader).getSnapshotReader(); - SVMImageLayerLoader.streamStrings(snapshotReader.getRegisteredJNILibraries()).forEach(singleton.prevLayerRegisteredLibraries::add); + CapnProtoAdapters.forEach(snapshotReader.getRegisteredJNILibraries(), singleton.prevLayerRegisteredLibraries::add); return singleton; } }