From 16f3acff1d15be804d84330860cd6703b768d82c Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Fri, 9 Aug 2024 16:28:33 +0200 Subject: [PATCH 1/5] Drop MonitorEnterTypeFlow, which is almost always saturated, but can lead to problems in layered builds. --- .../graal/pointsto/PointsToAnalysis.java | 18 +------ .../pointsto/flow/MethodTypeFlowBuilder.java | 13 ----- .../pointsto/flow/MonitorEnterTypeFlow.java | 53 ------------------- .../pointsto/typestate/PointsToStats.java | 4 -- .../hosted/dashboard/PointsToBreakdown.java | 2 - 5 files changed, 1 insertion(+), 89 deletions(-) delete mode 100644 substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MonitorEnterTypeFlow.java diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java index 50e072eb1b87..cb16fb4f2014 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java @@ -45,7 +45,6 @@ import com.oracle.graal.pointsto.api.HostVM; import com.oracle.graal.pointsto.api.PointstoOptions; import com.oracle.graal.pointsto.constraints.UnsupportedFeatures; -import com.oracle.graal.pointsto.flow.AllSynchronizedTypeFlow; import com.oracle.graal.pointsto.flow.AnyPrimitiveSourceTypeFlow; import com.oracle.graal.pointsto.flow.FieldTypeFlow; import com.oracle.graal.pointsto.flow.FormalParamTypeFlow; @@ -104,7 +103,6 @@ public abstract class PointsToAnalysis extends AbstractAnalysisEngine { */ private final boolean trackPrimitiveValues; private AnyPrimitiveSourceTypeFlow anyPrimitiveSourceTypeFlow; - private TypeFlow allSynchronizedTypeFlow; protected final boolean trackTypeFlowInputs; protected final boolean reportAnalysisStatistics; @@ -132,7 +130,6 @@ public PointsToAnalysis(OptionValues options, AnalysisUniverse universe, HostVM * instantiated types yet, so the state is empty at first. */ objectType.getTypeFlow(this, true); - allSynchronizedTypeFlow = new AllSynchronizedTypeFlow(); trackTypeFlowInputs = PointstoOptions.TrackInputFlows.getValue(options); reportAnalysisStatistics = PointstoOptions.PrintPointsToStatistics.getValue(options); @@ -258,7 +255,6 @@ public boolean trackConcreteAnalysisObjects(@SuppressWarnings("unused") Analysis @Override public void cleanupAfterAnalysis() { super.cleanupAfterAnalysis(); - allSynchronizedTypeFlow = null; anyPrimitiveSourceTypeFlow = null; unsafeLoads = null; unsafeStores = null; @@ -287,25 +283,13 @@ public Iterable getAllInstantiatedTypes() { return getAllInstantiatedTypeFlow().getState().types(this); } - public TypeFlow getAllSynchronizedTypeFlow() { - return allSynchronizedTypeFlow; - } - public AnyPrimitiveSourceTypeFlow getAnyPrimitiveSourceTypeFlow() { return anyPrimitiveSourceTypeFlow; } @Override public Iterable getAllSynchronizedTypes() { - /* - * If all-synchrnonized type flow, i.e., the type flow that keeps track of the types of all - * monitor objects, is saturated then we need to assume that any type can be used for - * monitors. - */ - if (allSynchronizedTypeFlow.isSaturated()) { - return getAllInstantiatedTypes(); - } - return allSynchronizedTypeFlow.getState().types(this); + return getAllInstantiatedTypes(); } @Override diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java index ee8097982b71..6892a5f9b26d 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java @@ -116,7 +116,6 @@ import jdk.graal.compiler.nodes.java.LoadFieldNode; import jdk.graal.compiler.nodes.java.LoadIndexedNode; import jdk.graal.compiler.nodes.java.MethodCallTargetNode; -import jdk.graal.compiler.nodes.java.MonitorEnterNode; import jdk.graal.compiler.nodes.java.NewArrayNode; import jdk.graal.compiler.nodes.java.NewArrayWithExceptionNode; import jdk.graal.compiler.nodes.java.NewInstanceNode; @@ -1122,18 +1121,6 @@ protected void node(FixedNode n) { }); cloneBuilder.addObserverDependency(inputBuilder); state.add(node.asFixedNode(), cloneBuilder); - } else if (n instanceof MonitorEnterNode) { - MonitorEnterNode node = (MonitorEnterNode) n; - TypeFlowBuilder objectBuilder = state.lookup(node.object()); - - TypeFlowBuilder monitorEntryBuilder = TypeFlowBuilder.create(bb, node, MonitorEnterTypeFlow.class, () -> { - MonitorEnterTypeFlow monitorEntryFlow = new MonitorEnterTypeFlow(AbstractAnalysisEngine.sourcePosition(node), bb); - flowsGraph.addMiscEntryFlow(monitorEntryFlow); - return monitorEntryFlow; - }); - monitorEntryBuilder.addUseDependency(objectBuilder); - /* Monitor enters must not be removed. */ - typeFlowGraphBuilder.registerSinkBuilder(monitorEntryBuilder); } else if (n instanceof MacroInvokable node) { /* * Macro nodes can either be constant folded during compilation, or lowered back to diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MonitorEnterTypeFlow.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MonitorEnterTypeFlow.java deleted file mode 100644 index 411fbb99d047..000000000000 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MonitorEnterTypeFlow.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2015, 2017, 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.graal.pointsto.flow; - -import com.oracle.graal.pointsto.PointsToAnalysis; - -import jdk.vm.ci.code.BytecodePosition; - -public class MonitorEnterTypeFlow extends TypeFlow { - - @SuppressWarnings("this-escape") - public MonitorEnterTypeFlow(BytecodePosition position, PointsToAnalysis bb) { - super(position, null); - this.addUse(bb, bb.getAllSynchronizedTypeFlow()); - } - - public BytecodePosition getLocation() { - return source; - } - - @Override - public TypeFlow copy(PointsToAnalysis bb, MethodFlowsGraph methodFlows) { - return this; - } - - @Override - public String toString() { - return "MonitorEnterFlow<" + getState() + ">"; - } - -} diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/PointsToStats.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/PointsToStats.java index 667ee6257ec9..13fc569cdea7 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/PointsToStats.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/PointsToStats.java @@ -61,7 +61,6 @@ import com.oracle.graal.pointsto.flow.LoadFieldTypeFlow.LoadInstanceFieldTypeFlow; import com.oracle.graal.pointsto.flow.LoadFieldTypeFlow.LoadStaticFieldTypeFlow; import com.oracle.graal.pointsto.flow.MergeTypeFlow; -import com.oracle.graal.pointsto.flow.MonitorEnterTypeFlow; import com.oracle.graal.pointsto.flow.NewInstanceTypeFlow; import com.oracle.graal.pointsto.flow.NullCheckTypeFlow; import com.oracle.graal.pointsto.flow.OffsetLoadTypeFlow.LoadIndexedTypeFlow; @@ -506,9 +505,6 @@ private static String asString(TypeFlow flow) { return "Source @ " + formatSource(flow); } else if (flow instanceof CloneTypeFlow) { return "Clone @ " + formatSource(flow); - } else if (flow instanceof MonitorEnterTypeFlow) { - MonitorEnterTypeFlow monitor = (MonitorEnterTypeFlow) flow; - return "MonitorEnter @ " + formatMethod(monitor.getSource().getMethod()); } else { return ClassUtil.getUnqualifiedName(flow.getClass()) + "@" + formatSource(flow); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/dashboard/PointsToBreakdown.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/dashboard/PointsToBreakdown.java index 97ad466a7cbb..f70fae0fcaaf 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/dashboard/PointsToBreakdown.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/dashboard/PointsToBreakdown.java @@ -59,7 +59,6 @@ import com.oracle.graal.pointsto.flow.LoadFieldTypeFlow; import com.oracle.graal.pointsto.flow.MergeTypeFlow; import com.oracle.graal.pointsto.flow.MethodFlowsGraph; -import com.oracle.graal.pointsto.flow.MonitorEnterTypeFlow; import com.oracle.graal.pointsto.flow.NewInstanceTypeFlow; import com.oracle.graal.pointsto.flow.NullCheckTypeFlow; import com.oracle.graal.pointsto.flow.OffsetLoadTypeFlow; @@ -361,7 +360,6 @@ public static class DashboardTypeFlowNames { names.put(FormalReceiverTypeFlow.class, "formalReceiver"); names.put(OffsetLoadTypeFlow.LoadIndexedTypeFlow.class, "loadIndexed"); names.put(MergeTypeFlow.class, "merge"); - names.put(MonitorEnterTypeFlow.class, "monitorEnter"); names.put(ProxyTypeFlow.class, "proxy"); names.put(SourceTypeFlow.class, "source"); names.put(OffsetStoreTypeFlow.StoreIndexedTypeFlow.class, "storeIndexed"); From ccb39e4eee27e3427d72e8f59282bf27e738b863 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Fri, 9 Aug 2024 17:26:56 +0200 Subject: [PATCH 2/5] Turn ImageHeapInfo into a MultiLayeredImageSingleton rather than linking objects together. --- .../genscavenge/CompactingOldGeneration.java | 2 +- .../oracle/svm/core/genscavenge/GCImpl.java | 4 ++-- .../oracle/svm/core/genscavenge/HeapImpl.java | 23 ++++++++++--------- .../svm/core/genscavenge/HeapVerifier.java | 4 ++-- .../svm/core/genscavenge/ImageHeapInfo.java | 19 ++++++++------- .../graal/GenScavengeGCFeature.java | 13 +++++++---- 6 files changed, 36 insertions(+), 29 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CompactingOldGeneration.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CompactingOldGeneration.java index f0de34f37a7f..d219f81d010c 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CompactingOldGeneration.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CompactingOldGeneration.java @@ -288,7 +288,7 @@ private void fixupReferencesBeforeCompaction(ChunkReleaser chunkReleaser, Timers Timer oldFixupImageHeapTimer = timers.oldFixupImageHeap.open(); try { - for (ImageHeapInfo info = HeapImpl.getFirstImageHeapInfo(); info != null; info = info.next) { + for (ImageHeapInfo info : HeapImpl.getImageHeapInfos()) { GCImpl.walkImageHeapRoots(info, fixupVisitor); } if (AuxiliaryImageHeap.isPresent()) { diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java index fd77d1607339..bd5510d304b7 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java @@ -913,7 +913,7 @@ private void blackenDirtyImageHeapRoots() { Timer blackenImageHeapRootsTimer = timers.blackenImageHeapRoots.open(); try { - for (ImageHeapInfo info = HeapImpl.getFirstImageHeapInfo(); info != null; info = info.next) { + for (ImageHeapInfo info : HeapImpl.getImageHeapInfos()) { blackenDirtyImageHeapChunkRoots(info.getFirstWritableAlignedChunk(), info.getFirstWritableUnalignedChunk(), info.getLastWritableUnalignedChunk()); } @@ -964,7 +964,7 @@ private void blackenImageHeapRoots() { Timer blackenImageHeapRootsTimer = timers.blackenImageHeapRoots.open(); try { - for (ImageHeapInfo info = HeapImpl.getFirstImageHeapInfo(); info != null; info = info.next) { + for (ImageHeapInfo info : HeapImpl.getImageHeapInfos()) { blackenImageHeapRoots(info); } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java index cc98db104231..ce83b03251ea 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java @@ -69,6 +69,7 @@ import com.oracle.svm.core.jdk.UninterruptibleUtils.AtomicReference; import com.oracle.svm.core.jfr.JfrTicks; import com.oracle.svm.core.jfr.events.SystemGCEvent; +import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton; import com.oracle.svm.core.locks.VMCondition; import com.oracle.svm.core.locks.VMMutex; import com.oracle.svm.core.log.Log; @@ -105,7 +106,6 @@ public final class HeapImpl extends Heap { private final ObjectHeaderImpl objectHeaderImpl = new ObjectHeaderImpl(); private final GCImpl gcImpl; private final RuntimeCodeInfoGCSupportImpl runtimeCodeInfoGcSupport; - private final ImageHeapInfo firstImageHeapInfo = new ImageHeapInfo(); private final HeapAccounting accounting = new HeapAccounting(); /** Head of the linked list of currently pending (ready to be enqueued) {@link Reference}s. */ @@ -140,9 +140,9 @@ public static HeapImpl getHeapImpl() { return (HeapImpl) heap; } - @Fold - public static ImageHeapInfo getFirstImageHeapInfo() { - return getHeapImpl().firstImageHeapInfo; + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public static ImageHeapInfo[] getImageHeapInfos() { + return MultiLayeredImageSingleton.getAllLayers(ImageHeapInfo.class); } @Fold @@ -177,7 +177,7 @@ public boolean isInPrimaryImageHeap(Object obj) { @Override @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public boolean isInPrimaryImageHeap(Pointer objPointer) { - for (ImageHeapInfo info = firstImageHeapInfo; info != null; info = info.next) { + for (ImageHeapInfo info : getImageHeapInfos()) { if (info.isInImageHeap(objPointer)) { return true; } @@ -284,9 +284,10 @@ void logChunks(Log log) { getChunkProvider().logFreeChunks(log); } + @SuppressWarnings("static-method") void logImageHeapPartitionBoundaries(Log log) { log.string("Native image heap boundaries:").indent(true); - for (ImageHeapInfo info = firstImageHeapInfo; info != null; info = info.next) { + for (ImageHeapInfo info : HeapImpl.getImageHeapInfos()) { info.print(log); } log.indent(false); @@ -331,8 +332,8 @@ static void logZapValues(Log log) { @Override @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public int getClassCount() { - int count = firstImageHeapInfo.dynamicHubCount; - for (ImageHeapInfo info = firstImageHeapInfo.next; info != null; info = info.next) { + int count = 0; + for (ImageHeapInfo info : HeapImpl.getImageHeapInfos()) { count += info.dynamicHubCount; } return count; @@ -354,7 +355,7 @@ private ArrayList> findAllDynamicHubs() { int dynamicHubCount = getClassCount(); ArrayList> list = new ArrayList<>(dynamicHubCount); - for (ImageHeapInfo info = firstImageHeapInfo; info != null; info = info.next) { + for (ImageHeapInfo info : HeapImpl.getImageHeapInfos()) { ImageHeapWalker.walkRegions(info, new ClassListBuilderVisitor(list.size() + info.dynamicHubCount, list)); } @@ -467,7 +468,7 @@ public boolean walkImageHeapObjects(ObjectVisitor visitor) { if (visitor == null) { return true; } - for (ImageHeapInfo info = firstImageHeapInfo; info != null; info = info.next) { + for (ImageHeapInfo info : HeapImpl.getImageHeapInfos()) { if (!ImageHeapWalker.walkImageHeapObjects(info, visitor)) { return false; } @@ -731,7 +732,7 @@ public UnsignedWord getUsedMemoryAfterLastGC() { } private boolean printLocationInfo(Log log, Pointer ptr, boolean allowJavaHeapAccess, boolean allowUnsafeOperations) { - for (ImageHeapInfo info = firstImageHeapInfo; info != null; info = info.next) { + for (ImageHeapInfo info : HeapImpl.getImageHeapInfos()) { if (info.isInReadOnlyRegularPartition(ptr)) { log.string("points into the image heap (read-only)"); return true; diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapVerifier.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapVerifier.java index 20bfd41ac7f2..91e1856014ea 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapVerifier.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapVerifier.java @@ -73,7 +73,7 @@ public boolean verify(Occasion occasion) { protected boolean verifyImageHeap() { boolean success = true; - for (ImageHeapInfo info = HeapImpl.getFirstImageHeapInfo(); info != null; info = info.next) { + for (ImageHeapInfo info : HeapImpl.getImageHeapInfos()) { success &= verifyAlignedChunks(null, info.getFirstWritableAlignedChunk()); success &= verifyUnalignedChunks(null, info.getFirstWritableUnalignedChunk(), info.getLastWritableUnalignedChunk()); } @@ -129,7 +129,7 @@ private static boolean verifyRememberedSets() { boolean success = true; RememberedSet rememberedSet = RememberedSet.get(); - for (ImageHeapInfo info = HeapImpl.getFirstImageHeapInfo(); info != null; info = info.next) { + for (ImageHeapInfo info : HeapImpl.getImageHeapInfos()) { success &= rememberedSet.verify(info.getFirstWritableAlignedChunk()); success &= rememberedSet.verify(info.getFirstWritableUnalignedChunk(), info.getLastWritableUnalignedChunk()); } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ImageHeapInfo.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ImageHeapInfo.java index 62f133c81d2d..8aae5b0ad445 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ImageHeapInfo.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ImageHeapInfo.java @@ -24,6 +24,8 @@ */ package com.oracle.svm.core.genscavenge; +import java.util.EnumSet; + import org.graalvm.word.Pointer; import org.graalvm.word.UnsignedWord; import org.graalvm.word.WordFactory; @@ -35,6 +37,9 @@ import com.oracle.svm.core.heap.UnknownObjectField; import com.oracle.svm.core.heap.UnknownPrimitiveField; import com.oracle.svm.core.hub.LayoutEncoding; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton; +import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; import com.oracle.svm.core.log.Log; import com.oracle.svm.core.snippets.KnownIntrinsics; @@ -44,7 +49,7 @@ * Information on the multiple partitions that make up the image heap, which don't necessarily form * a contiguous block of memory (there can be holes in between), and their boundaries. */ -public final class ImageHeapInfo { +public final class ImageHeapInfo implements MultiLayeredImageSingleton, UnsavedSingleton { /** Indicates no chunk with {@link #initialize} chunk offset parameters. */ public static final long NO_CHUNK = -1; @@ -73,14 +78,7 @@ public final class ImageHeapInfo { @UnknownPrimitiveField(availability = AfterHeapLayout.class) public int dynamicHubCount; - public final ImageHeapInfo next; - public ImageHeapInfo() { - this(null); - } - - public ImageHeapInfo(ImageHeapInfo next) { - this.next = next; } @SuppressWarnings("hiding") @@ -205,4 +203,9 @@ public void print(Log log) { log.string("Writable Huge: ").zhex(Word.objectToUntrackedPointer(firstWritableHugeObject)).string(" - ").zhex(getObjectEnd(lastWritableHugeObject)).newline(); log.string("ReadOnly Huge: ").zhex(Word.objectToUntrackedPointer(firstReadOnlyHugeObject)).string(" - ").zhex(getObjectEnd(lastReadOnlyHugeObject)).newline(); } + + @Override + public EnumSet getImageBuilderFlags() { + return LayeredImageSingletonBuilderFlags.ALL_ACCESS; + } } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java index bccf67fc10da..fe67125edde0 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java @@ -90,8 +90,8 @@ public void afterRegistration(AfterRegistrationAccess access) { @Override public void duringSetup(DuringSetupAccess access) { - HeapImpl heap = new HeapImpl(); - ImageSingletons.add(Heap.class, heap); + ImageSingletons.add(Heap.class, new HeapImpl()); + ImageSingletons.add(ImageHeapInfo.class, new ImageHeapInfo()); ImageSingletons.add(GCAllocationSupport.class, new GenScavengeAllocationSupport()); if (ImageSingletons.contains(PerfManager.class)) { @@ -125,16 +125,19 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { access.registerAsUsed(Object[].class); } + private static ImageHeapInfo getImageHeapInfo() { + return ImageSingletons.lookup(ImageHeapInfo.class); + } + @Override public void afterAnalysis(AfterAnalysisAccess access) { - ImageHeapLayouter heapLayouter = new ChunkedImageHeapLayouter(HeapImpl.getFirstImageHeapInfo(), Heap.getHeap().getImageHeapOffsetInAddressSpace()); + ImageHeapLayouter heapLayouter = new ChunkedImageHeapLayouter(getImageHeapInfo(), Heap.getHeap().getImageHeapOffsetInAddressSpace()); ImageSingletons.add(ImageHeapLayouter.class, heapLayouter); } @Override public void beforeCompilation(BeforeCompilationAccess access) { - ImageHeapInfo imageHeapInfo = HeapImpl.getFirstImageHeapInfo(); - access.registerAsImmutable(imageHeapInfo); + access.registerAsImmutable(getImageHeapInfo()); } @Override From ec0c58766e99b8f9dffd4e9d178af3c0d00051e6 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Fri, 9 Aug 2024 17:30:10 +0200 Subject: [PATCH 3/5] Support per-layer type reference maps. --- .../jdk/SubstrateObjectCloneSnippets.java | 6 +- .../com/oracle/svm/core/hub/DynamicHub.java | 8 +-- .../svm/core/hub/DynamicHubSupport.java | 58 ++++++++++++++++++- .../svm/core/hub/InteriorObjRefWalker.java | 15 +++-- .../hosted/image/ObjectGroupHistogram.java | 2 +- .../svm/hosted/meta/UniverseBuilder.java | 6 +- 6 files changed, 74 insertions(+), 21 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateObjectCloneSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateObjectCloneSnippets.java index b05a41d32c37..b77a9b20d427 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateObjectCloneSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateObjectCloneSnippets.java @@ -127,9 +127,11 @@ private static Object doClone(Object original) throws CloneNotSupportedException int firstFieldOffset = ConfigurationValues.getObjectLayout().getFirstFieldOffset(); int curOffset = firstFieldOffset; - NonmovableArray referenceMapEncoding = DynamicHubSupport.getReferenceMapEncoding(); int referenceSize = ConfigurationValues.getObjectLayout().getReferenceSize(); - int referenceMapIndex = hub.getReferenceMapIndex(); + int globalRefMapIndex = hub.getGlobalReferenceMapIndex(); + DynamicHubSupport hubSupport = DynamicHubSupport.forGlobalReferenceMapIndex(globalRefMapIndex); + NonmovableArray referenceMapEncoding = hubSupport.getReferenceMapEncoding(); + int referenceMapIndex = globalRefMapIndex - hubSupport.getFirstReferenceMapIndex(); int entryCount = NonmovableByteArrayReader.getS4(referenceMapEncoding, referenceMapIndex); assert entryCount >= 0; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java index c8a604b3f0ce..e34ee10b5a82 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java @@ -361,7 +361,7 @@ public final class DynamicHub implements AnnotatedElement, java.lang.reflect.Typ * {@link DynamicHubSupport#getReferenceMapEncoding()}. */ @UnknownPrimitiveField(availability = AfterHostedUniverse.class)// - private int referenceMapIndex; + private int globalReferenceMapIndex; /** * Back link to the SubstrateType used by the substrate meta access. Only used for the subset of @@ -499,7 +499,7 @@ public void setSharedData(int layoutEncoding, int monitorOffset, int identityHas if ((int) referenceMapIndex != referenceMapIndex) { throw VMError.shouldNotReachHere("Reference map index not within integer range, need to switch field from int to long"); } - this.referenceMapIndex = (int) referenceMapIndex; + this.globalReferenceMapIndex = (int) referenceMapIndex; this.additionalFlags = NumUtil.safeToUByte(makeFlag(IS_INSTANTIATED_BIT, isInstantiated)); } @@ -733,8 +733,8 @@ public DynamicHub getArrayHub() { } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - public int getReferenceMapIndex() { - return referenceMapIndex; + public int getGlobalReferenceMapIndex() { + return globalReferenceMapIndex; } public boolean isInstantiated() { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubSupport.java index 2ea055c6f21f..3385a123323a 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubSupport.java @@ -24,6 +24,8 @@ */ package com.oracle.svm.core.hub; +import java.util.EnumSet; + import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -35,21 +37,50 @@ import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; import com.oracle.svm.core.heap.UnknownObjectField; import com.oracle.svm.core.heap.UnknownPrimitiveField; +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; +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.core.layeredimagesingleton.MultiLayeredImageSingleton; +import com.oracle.svm.core.util.VMError; @AutomaticallyRegisteredImageSingleton -public final class DynamicHubSupport { +public final class DynamicHubSupport implements MultiLayeredImageSingleton { @UnknownPrimitiveField(availability = AfterHostedUniverse.class) private int maxTypeId; @UnknownObjectField(availability = AfterHostedUniverse.class) private byte[] referenceMapEncoding; + @UnknownPrimitiveField(availability = AfterHostedUniverse.class) private int firstReferenceMapIndex; + @Platforms(Platform.HOSTED_ONLY.class) public static DynamicHubSupport singleton() { return ImageSingletons.lookup(DynamicHubSupport.class); } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public static DynamicHubSupport forGlobalReferenceMapIndex(int globalReferenceMapIndex) { + if (!ImageLayerBuildingSupport.buildingImageLayer()) { + return ImageSingletons.lookup(DynamicHubSupport.class); + } + + DynamicHubSupport[] all = MultiLayeredImageSingleton.getAllLayers(DynamicHubSupport.class); + for (DynamicHubSupport hubSupport : all) { + int referenceMapIndex = globalReferenceMapIndex - hubSupport.firstReferenceMapIndex; + if (referenceMapIndex >= 0 && referenceMapIndex < hubSupport.referenceMapEncoding.length) { + return hubSupport; + } + } + throw VMError.shouldNotReachHereAtRuntime(); + } + @Platforms(Platform.HOSTED_ONLY.class) public DynamicHubSupport() { } + @Platforms(Platform.HOSTED_ONLY.class) + private DynamicHubSupport(int firstReferenceMapIndex) { + this.firstReferenceMapIndex = firstReferenceMapIndex; + } + @Platforms(Platform.HOSTED_ONLY.class) public void setMaxTypeId(int maxTypeId) { this.maxTypeId = maxTypeId; @@ -66,7 +97,28 @@ public void setReferenceMapEncoding(NonmovableArray referenceMapEncoding) } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - public static NonmovableArray getReferenceMapEncoding() { - return NonmovableArrays.fromImageHeap(ImageSingletons.lookup(DynamicHubSupport.class).referenceMapEncoding); + public int getFirstReferenceMapIndex() { + return firstReferenceMapIndex; + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public NonmovableArray getReferenceMapEncoding() { + return NonmovableArrays.fromImageHeap(referenceMapEncoding); + } + + @Override + public EnumSet getImageBuilderFlags() { + return LayeredImageSingletonBuilderFlags.ALL_ACCESS; + } + + @Override + public PersistFlags preparePersist(ImageSingletonWriter writer) { + writer.writeInt("nextReferenceMapIndex", firstReferenceMapIndex + referenceMapEncoding.length); + return PersistFlags.CREATE; + } + + public static Object createFromLoader(ImageSingletonLoader loader) { + int nextReferenceMapIndex = loader.readInt("nextReferenceMapIndex"); + return new DynamicHubSupport(nextReferenceMapIndex); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/InteriorObjRefWalker.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/InteriorObjRefWalker.java index c86044d5a763..742028aa5a44 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/InteriorObjRefWalker.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/InteriorObjRefWalker.java @@ -100,24 +100,23 @@ public static boolean walkInstanceReferenceOffsets(DynamicHub objHub, IntConsume if (objHub.getHubType() != HubType.INSTANCE && objHub.getHubType() != HubType.REFERENCE_INSTANCE) { throw new IllegalArgumentException("Unsupported hub type: " + objHub.getHubType()); } - - NonmovableArray referenceMapEncoding = DynamicHubSupport.getReferenceMapEncoding(); - long referenceMapIndex = objHub.getReferenceMapIndex(); - - return InstanceReferenceMapDecoder.walkOffsetsFromPointer(WordFactory.zero(), referenceMapEncoding, referenceMapIndex, new ObjectReferenceVisitor() { + ObjectReferenceVisitor visitor = new ObjectReferenceVisitor() { @Override public boolean visitObjectReference(Pointer objRef, boolean compressed, Object holderObject) { offsetConsumer.accept((int) objRef.rawValue()); return true; } - }, null); + }; + return walkInstance(null, visitor, objHub, WordFactory.zero()); } @AlwaysInline("Performance critical version") @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) private static boolean walkInstance(Object obj, ObjectReferenceVisitor visitor, DynamicHub objHub, Pointer objPointer) { - NonmovableArray referenceMapEncoding = DynamicHubSupport.getReferenceMapEncoding(); - long referenceMapIndex = objHub.getReferenceMapIndex(); + int globalReferenceMapIndex = objHub.getGlobalReferenceMapIndex(); + DynamicHubSupport hubSupport = DynamicHubSupport.forGlobalReferenceMapIndex(globalReferenceMapIndex); + NonmovableArray referenceMapEncoding = hubSupport.getReferenceMapEncoding(); + int referenceMapIndex = globalReferenceMapIndex - hubSupport.getFirstReferenceMapIndex(); // Visit Object reference in the fields of the Object. return InstanceReferenceMapDecoder.walkOffsetsFromPointer(objPointer, referenceMapEncoding, referenceMapIndex, visitor, obj); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/ObjectGroupHistogram.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/ObjectGroupHistogram.java index 85c2ab1f5fab..c9b93c356121 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/ObjectGroupHistogram.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/ObjectGroupHistogram.java @@ -105,7 +105,7 @@ private void doPrint() { * order in which types are prcessed matters. */ processType(DynamicHub.class, "DynamicHub", true, null, ObjectGroupHistogram::filterDynamicHubField); - processObject(NonmovableArrays.getHostedArray(DynamicHubSupport.getReferenceMapEncoding()), "DynamicHub", true, null, null); + processObject(NonmovableArrays.getHostedArray(DynamicHubSupport.singleton().getReferenceMapEncoding()), "DynamicHub", true, null, null); processObject(CodeInfoTable.getImageCodeCache(), "ImageCodeInfo", true, ObjectGroupHistogram::filterCodeInfoObjects, null); processObject(readTruffleRuntimeCompilationSupportField("graphEncoding"), "CompressedGraph", true, ObjectGroupHistogram::filterGraalSupportObjects, null); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java index c1af300c33ff..e32a8872acbb 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java @@ -865,6 +865,7 @@ private void buildHubs() { referenceMaps.put(type, referenceMap); referenceMapEncoder.add(referenceMap); } + int firstReferenceMapIndex = DynamicHubSupport.singleton().getFirstReferenceMapIndex(); DynamicHubSupport.singleton().setReferenceMapEncoding(referenceMapEncoder.encodeAll()); ObjectLayout ol = ConfigurationValues.getObjectLayout(); @@ -911,11 +912,10 @@ private void buildHubs() { ReferenceMapEncoder.Input referenceMap = referenceMaps.get(type); assert referenceMap != null; assert ((SubstrateReferenceMap) referenceMap).hasNoDerivedOffsets(); - long referenceMapIndex = referenceMapEncoder.lookupEncoding(referenceMap); + long globalReferenceMapIndex = firstReferenceMapIndex + referenceMapEncoder.lookupEncoding(referenceMap); DynamicHub hub = type.getHub(); - hub.setSharedData(layoutHelper, monitorOffset, identityHashOffset, - referenceMapIndex, type.isInstantiated()); + hub.setSharedData(layoutHelper, monitorOffset, identityHashOffset, globalReferenceMapIndex, type.isInstantiated()); if (SubstrateOptions.closedTypeWorld()) { CFunctionPointer[] vtable = new CFunctionPointer[type.closedTypeWorldVTable.length]; From 4f7e4f8c61c40d8a3051aa66ac8e983b4437940b Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Sat, 10 Aug 2024 12:48:51 +0200 Subject: [PATCH 4/5] Access heap reference maps using a layer id rather than globally continuous indexes. --- .../jdk/SubstrateObjectCloneSnippets.java | 6 +-- .../com/oracle/svm/core/hub/DynamicHub.java | 26 +++++++++--- .../svm/core/hub/DynamicHubSupport.java | 40 +++++++++---------- .../svm/core/hub/InteriorObjRefWalker.java | 15 +++---- .../src/com/oracle/svm/hosted/SVMHost.java | 5 ++- .../svm/hosted/meta/UniverseBuilder.java | 5 +-- 6 files changed, 55 insertions(+), 42 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateObjectCloneSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateObjectCloneSnippets.java index b77a9b20d427..99aa7eed79b6 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateObjectCloneSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateObjectCloneSnippets.java @@ -127,11 +127,9 @@ private static Object doClone(Object original) throws CloneNotSupportedException int firstFieldOffset = ConfigurationValues.getObjectLayout().getFirstFieldOffset(); int curOffset = firstFieldOffset; + NonmovableArray referenceMapEncoding = DynamicHubSupport.forLayer(hub.getLayerId()).getReferenceMapEncoding(); int referenceSize = ConfigurationValues.getObjectLayout().getReferenceSize(); - int globalRefMapIndex = hub.getGlobalReferenceMapIndex(); - DynamicHubSupport hubSupport = DynamicHubSupport.forGlobalReferenceMapIndex(globalRefMapIndex); - NonmovableArray referenceMapEncoding = hubSupport.getReferenceMapEncoding(); - int referenceMapIndex = globalRefMapIndex - hubSupport.getFirstReferenceMapIndex(); + int referenceMapIndex = hub.getReferenceMapIndex(); int entryCount = NonmovableByteArrayReader.getS4(referenceMapEncoding, referenceMapIndex); assert entryCount >= 0; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java index e34ee10b5a82..7c88c23dbace 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java @@ -361,7 +361,9 @@ public final class DynamicHub implements AnnotatedElement, java.lang.reflect.Typ * {@link DynamicHubSupport#getReferenceMapEncoding()}. */ @UnknownPrimitiveField(availability = AfterHostedUniverse.class)// - private int globalReferenceMapIndex; + private int referenceMapIndex; + + private final byte layerId; /** * Back link to the SubstrateType used by the substrate meta access. Only used for the subset of @@ -432,7 +434,10 @@ public final class DynamicHub implements AnnotatedElement, java.lang.reflect.Typ @Platforms(Platform.HOSTED_ONLY.class) public DynamicHub(Class hostedJavaClass, String name, int hubType, ReferenceType referenceType, DynamicHub superType, DynamicHub componentHub, String sourceFileName, int modifiers, ClassLoader classLoader, boolean isHidden, boolean isRecord, Class nestHost, boolean assertionStatus, boolean hasDefaultMethods, boolean declaresDefaultMethods, - boolean isSealed, boolean isVMInternal, boolean isLambdaFormHidden, boolean isLinked, String simpleBinaryName, Object declaringClass, String signature, boolean isProxyClass) { + boolean isSealed, boolean isVMInternal, boolean isLambdaFormHidden, boolean isLinked, String simpleBinaryName, Object declaringClass, String signature, boolean isProxyClass, + int layerId) { + VMError.guarantee(layerId == (byte) layerId, "Layer id %d not in expected range", layerId); + this.hostedJavaClass = hostedJavaClass; this.module = hostedJavaClass.getModule(); this.name = name; @@ -446,6 +451,7 @@ public DynamicHub(Class hostedJavaClass, String name, int hubType, ReferenceT this.simpleBinaryName = simpleBinaryName; this.declaringClass = declaringClass; this.signature = signature; + this.layerId = (byte) layerId; this.flags = NumUtil.safeToUShort(makeFlag(IS_PRIMITIVE_FLAG_BIT, hostedJavaClass.isPrimitive()) | makeFlag(IS_INTERFACE_FLAG_BIT, hostedJavaClass.isInterface()) | @@ -499,7 +505,7 @@ public void setSharedData(int layoutEncoding, int monitorOffset, int identityHas if ((int) referenceMapIndex != referenceMapIndex) { throw VMError.shouldNotReachHere("Reference map index not within integer range, need to switch field from int to long"); } - this.globalReferenceMapIndex = (int) referenceMapIndex; + this.referenceMapIndex = (int) referenceMapIndex; this.additionalFlags = NumUtil.safeToUByte(makeFlag(IS_INSTANTIATED_BIT, isInstantiated)); } @@ -733,8 +739,18 @@ public DynamicHub getArrayHub() { } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - public int getGlobalReferenceMapIndex() { - return globalReferenceMapIndex; + public int getReferenceMapIndex() { + return referenceMapIndex; + } + + /** + * The identifier of the {@linkplain com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport + * layer} that introduces this type which is an index into the array returned by + * {@link com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton#getAllLayers}. + */ + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public int getLayerId() { + return layerId; } public boolean isInstantiated() { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubSupport.java index 3385a123323a..d301b5bcc740 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubSupport.java @@ -30,6 +30,7 @@ import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; +import com.oracle.svm.core.AlwaysInline; import com.oracle.svm.core.BuildPhaseProvider.AfterHostedUniverse; import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.c.NonmovableArray; @@ -42,43 +43,43 @@ import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton; -import com.oracle.svm.core.util.VMError; @AutomaticallyRegisteredImageSingleton public final class DynamicHubSupport implements MultiLayeredImageSingleton { + private final int layerId; @UnknownPrimitiveField(availability = AfterHostedUniverse.class) private int maxTypeId; @UnknownObjectField(availability = AfterHostedUniverse.class) private byte[] referenceMapEncoding; - @UnknownPrimitiveField(availability = AfterHostedUniverse.class) private int firstReferenceMapIndex; @Platforms(Platform.HOSTED_ONLY.class) public static DynamicHubSupport singleton() { return ImageSingletons.lookup(DynamicHubSupport.class); } + @AlwaysInline("Performance") @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - public static DynamicHubSupport forGlobalReferenceMapIndex(int globalReferenceMapIndex) { + public static DynamicHubSupport forLayer(int layerIndex) { if (!ImageLayerBuildingSupport.buildingImageLayer()) { return ImageSingletons.lookup(DynamicHubSupport.class); } - - DynamicHubSupport[] all = MultiLayeredImageSingleton.getAllLayers(DynamicHubSupport.class); - for (DynamicHubSupport hubSupport : all) { - int referenceMapIndex = globalReferenceMapIndex - hubSupport.firstReferenceMapIndex; - if (referenceMapIndex >= 0 && referenceMapIndex < hubSupport.referenceMapEncoding.length) { - return hubSupport; - } - } - throw VMError.shouldNotReachHereAtRuntime(); + DynamicHubSupport[] supports = MultiLayeredImageSingleton.getAllLayers(DynamicHubSupport.class); + return supports[layerIndex]; } @Platforms(Platform.HOSTED_ONLY.class) public DynamicHubSupport() { + this(0); + } + + @Platforms(Platform.HOSTED_ONLY.class) + private DynamicHubSupport(int layerId) { + this.layerId = layerId; } + /** @see com.oracle.svm.core.hub.DynamicHub#getLayerId() */ @Platforms(Platform.HOSTED_ONLY.class) - private DynamicHubSupport(int firstReferenceMapIndex) { - this.firstReferenceMapIndex = firstReferenceMapIndex; + public int getLayerId() { + return layerId; } @Platforms(Platform.HOSTED_ONLY.class) @@ -96,11 +97,6 @@ public void setReferenceMapEncoding(NonmovableArray referenceMapEncoding) this.referenceMapEncoding = NonmovableArrays.getHostedArray(referenceMapEncoding); } - @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - public int getFirstReferenceMapIndex() { - return firstReferenceMapIndex; - } - @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public NonmovableArray getReferenceMapEncoding() { return NonmovableArrays.fromImageHeap(referenceMapEncoding); @@ -113,12 +109,12 @@ public EnumSet getImageBuilderFlags() { @Override public PersistFlags preparePersist(ImageSingletonWriter writer) { - writer.writeInt("nextReferenceMapIndex", firstReferenceMapIndex + referenceMapEncoding.length); + writer.writeInt("layerId", layerId); return PersistFlags.CREATE; } public static Object createFromLoader(ImageSingletonLoader loader) { - int nextReferenceMapIndex = loader.readInt("nextReferenceMapIndex"); - return new DynamicHubSupport(nextReferenceMapIndex); + int previousLayerId = loader.readInt("layerId"); + return new DynamicHubSupport(1 + previousLayerId); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/InteriorObjRefWalker.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/InteriorObjRefWalker.java index 742028aa5a44..8ffa4550e36d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/InteriorObjRefWalker.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/InteriorObjRefWalker.java @@ -100,23 +100,24 @@ public static boolean walkInstanceReferenceOffsets(DynamicHub objHub, IntConsume if (objHub.getHubType() != HubType.INSTANCE && objHub.getHubType() != HubType.REFERENCE_INSTANCE) { throw new IllegalArgumentException("Unsupported hub type: " + objHub.getHubType()); } - ObjectReferenceVisitor visitor = new ObjectReferenceVisitor() { + + NonmovableArray referenceMapEncoding = DynamicHubSupport.forLayer(objHub.getLayerId()).getReferenceMapEncoding(); + long referenceMapIndex = objHub.getReferenceMapIndex(); + + return InstanceReferenceMapDecoder.walkOffsetsFromPointer(WordFactory.zero(), referenceMapEncoding, referenceMapIndex, new ObjectReferenceVisitor() { @Override public boolean visitObjectReference(Pointer objRef, boolean compressed, Object holderObject) { offsetConsumer.accept((int) objRef.rawValue()); return true; } - }; - return walkInstance(null, visitor, objHub, WordFactory.zero()); + }, null); } @AlwaysInline("Performance critical version") @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) private static boolean walkInstance(Object obj, ObjectReferenceVisitor visitor, DynamicHub objHub, Pointer objPointer) { - int globalReferenceMapIndex = objHub.getGlobalReferenceMapIndex(); - DynamicHubSupport hubSupport = DynamicHubSupport.forGlobalReferenceMapIndex(globalReferenceMapIndex); - NonmovableArray referenceMapEncoding = hubSupport.getReferenceMapEncoding(); - int referenceMapIndex = globalReferenceMapIndex - hubSupport.getFirstReferenceMapIndex(); + NonmovableArray referenceMapEncoding = DynamicHubSupport.forLayer(objHub.getLayerId()).getReferenceMapEncoding(); + long referenceMapIndex = objHub.getReferenceMapIndex(); // Visit Object reference in the fields of the Object. return InstanceReferenceMapDecoder.walkOffsetsFromPointer(objPointer, referenceMapEncoding, referenceMapIndex, visitor, obj); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java index 600ce9024967..2bea10028445 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java @@ -87,6 +87,7 @@ import com.oracle.svm.core.heap.Target_java_lang_ref_Reference; import com.oracle.svm.core.heap.UnknownClass; import com.oracle.svm.core.hub.DynamicHub; +import com.oracle.svm.core.hub.DynamicHubSupport; import com.oracle.svm.core.hub.HubType; import com.oracle.svm.core.hub.Hybrid; import com.oracle.svm.core.hub.PredefinedClassesSupport; @@ -191,6 +192,7 @@ public enum UsageKind { private final FieldValueInterceptionSupport fieldValueInterceptionSupport; private final MissingRegistrationSupport missingRegistrationSupport; + private final int layerId; private final boolean useBaseLayer; private Set excludedFields; @@ -224,6 +226,7 @@ public SVMHost(OptionValues options, ImageClassLoader loader, ClassInitializatio } fieldValueInterceptionSupport = new FieldValueInterceptionSupport(annotationSubstitutions, classInitializationSupport); ImageSingletons.add(FieldValueInterceptionSupport.class, fieldValueInterceptionSupport); + layerId = DynamicHubSupport.singleton().getLayerId(); useBaseLayer = ImageLayerBuildingSupport.buildingExtensionLayer(); if (SubstrateOptions.includeAll()) { initializeExcludedFields(); @@ -490,7 +493,7 @@ private DynamicHub createHub(AnalysisType type) { return new DynamicHub(javaClass, className, computeHubType(type), computeReferenceType(type), superHub, componentHub, sourceFileName, modifiers, hubClassLoader, isHidden, isRecord, nestHost, assertionStatus, type.hasDefaultMethods(), type.declaresDefaultMethods(), isSealed, isVMInternal, isLambdaFormHidden, isLinked, simpleBinaryName, - getDeclaringClass(javaClass), getSignature(javaClass), isProxyClass); + getDeclaringClass(javaClass), getSignature(javaClass), isProxyClass, layerId); } private static final Method getSignature = ReflectionUtil.lookupMethod(Class.class, "getGenericSignature0"); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java index e32a8872acbb..b93b4879f7f1 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java @@ -865,7 +865,6 @@ private void buildHubs() { referenceMaps.put(type, referenceMap); referenceMapEncoder.add(referenceMap); } - int firstReferenceMapIndex = DynamicHubSupport.singleton().getFirstReferenceMapIndex(); DynamicHubSupport.singleton().setReferenceMapEncoding(referenceMapEncoder.encodeAll()); ObjectLayout ol = ConfigurationValues.getObjectLayout(); @@ -912,10 +911,10 @@ private void buildHubs() { ReferenceMapEncoder.Input referenceMap = referenceMaps.get(type); assert referenceMap != null; assert ((SubstrateReferenceMap) referenceMap).hasNoDerivedOffsets(); - long globalReferenceMapIndex = firstReferenceMapIndex + referenceMapEncoder.lookupEncoding(referenceMap); + long referenceMapIndex = referenceMapEncoder.lookupEncoding(referenceMap); DynamicHub hub = type.getHub(); - hub.setSharedData(layoutHelper, monitorOffset, identityHashOffset, globalReferenceMapIndex, type.isInstantiated()); + hub.setSharedData(layoutHelper, monitorOffset, identityHashOffset, referenceMapIndex, type.isInstantiated()); if (SubstrateOptions.closedTypeWorld()) { CFunctionPointer[] vtable = new CFunctionPointer[type.closedTypeWorldVTable.length]; From 45f1b1791ee2b813416157cdc6a75ded68624805 Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Wed, 21 Aug 2024 10:52:00 +0200 Subject: [PATCH 5/5] use layerNumber from DynamicImagerLayerInfo for assigning a hub's layer id --- .../svm/core/hub/DynamicHubSupport.java | 29 ++----------------- .../src/com/oracle/svm/hosted/SVMHost.java | 4 +-- 2 files changed, 4 insertions(+), 29 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubSupport.java index d301b5bcc740..a9d8b038458d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubSupport.java @@ -39,15 +39,13 @@ import com.oracle.svm.core.heap.UnknownObjectField; import com.oracle.svm.core.heap.UnknownPrimitiveField; import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; -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.core.layeredimagesingleton.MultiLayeredImageSingleton; +import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; @AutomaticallyRegisteredImageSingleton -public final class DynamicHubSupport implements MultiLayeredImageSingleton { +public final class DynamicHubSupport implements MultiLayeredImageSingleton, UnsavedSingleton { - private final int layerId; @UnknownPrimitiveField(availability = AfterHostedUniverse.class) private int maxTypeId; @UnknownObjectField(availability = AfterHostedUniverse.class) private byte[] referenceMapEncoding; @@ -68,18 +66,6 @@ public static DynamicHubSupport forLayer(int layerIndex) { @Platforms(Platform.HOSTED_ONLY.class) public DynamicHubSupport() { - this(0); - } - - @Platforms(Platform.HOSTED_ONLY.class) - private DynamicHubSupport(int layerId) { - this.layerId = layerId; - } - - /** @see com.oracle.svm.core.hub.DynamicHub#getLayerId() */ - @Platforms(Platform.HOSTED_ONLY.class) - public int getLayerId() { - return layerId; } @Platforms(Platform.HOSTED_ONLY.class) @@ -106,15 +92,4 @@ public NonmovableArray getReferenceMapEncoding() { public EnumSet getImageBuilderFlags() { return LayeredImageSingletonBuilderFlags.ALL_ACCESS; } - - @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - writer.writeInt("layerId", layerId); - return PersistFlags.CREATE; - } - - public static Object createFromLoader(ImageSingletonLoader loader) { - int previousLayerId = loader.readInt("layerId"); - return new DynamicHubSupport(1 + previousLayerId); - } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java index 2bea10028445..4eb4ec502a76 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java @@ -87,11 +87,11 @@ import com.oracle.svm.core.heap.Target_java_lang_ref_Reference; import com.oracle.svm.core.heap.UnknownClass; import com.oracle.svm.core.hub.DynamicHub; -import com.oracle.svm.core.hub.DynamicHubSupport; import com.oracle.svm.core.hub.HubType; import com.oracle.svm.core.hub.Hybrid; import com.oracle.svm.core.hub.PredefinedClassesSupport; import com.oracle.svm.core.hub.ReferenceType; +import com.oracle.svm.core.imagelayer.DynamicImageLayerInfo; import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.interpreter.InterpreterSupport; import com.oracle.svm.core.jdk.InternalVMMethod; @@ -226,7 +226,7 @@ public SVMHost(OptionValues options, ImageClassLoader loader, ClassInitializatio } fieldValueInterceptionSupport = new FieldValueInterceptionSupport(annotationSubstitutions, classInitializationSupport); ImageSingletons.add(FieldValueInterceptionSupport.class, fieldValueInterceptionSupport); - layerId = DynamicHubSupport.singleton().getLayerId(); + layerId = ImageLayerBuildingSupport.buildingImageLayer() ? DynamicImageLayerInfo.singleton().layerNumber : 0; useBaseLayer = ImageLayerBuildingSupport.buildingExtensionLayer(); if (SubstrateOptions.includeAll()) { initializeExcludedFields();