Skip to content

Commit

Permalink
[GR-53508] Refactor cross layer calls and link base layer .so.
Browse files Browse the repository at this point in the history
PullRequest: graal/17561
  • Loading branch information
cstancu committed Apr 26, 2024
2 parents 5f68ad3 + dd58510 commit 69d3c62
Show file tree
Hide file tree
Showing 16 changed files with 230 additions and 71 deletions.
Expand Up @@ -261,6 +261,10 @@ public ImageLayerLoader(ImageLayerSnapshotUtil imageLayerSnapshotUtil, List<Path
this.loadPaths = loadPaths;
}

public List<Path> getLoadPaths() {
return loadPaths;
}

public void setUniverse(AnalysisUniverse newUniverse) {
this.universe = newUniverse;
}
Expand Down
Expand Up @@ -43,6 +43,7 @@
import java.util.EnumSet;
import java.util.function.BiConsumer;

import com.oracle.svm.core.graal.code.CGlobalDataInfo;
import org.graalvm.collections.EconomicMap;
import org.graalvm.nativeimage.ImageSingletons;

Expand All @@ -53,6 +54,7 @@
import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.amd64.AMD64CPUFeatureAccess;
import com.oracle.svm.core.code.BaseLayerMethodAccessor;
import com.oracle.svm.core.config.ConfigurationValues;
import com.oracle.svm.core.cpufeature.Stubs;
import com.oracle.svm.core.deopt.Deoptimizer;
Expand All @@ -79,7 +81,6 @@
import com.oracle.svm.core.graal.nodes.ComputedIndirectCallTargetNode.Computation;
import com.oracle.svm.core.graal.nodes.ComputedIndirectCallTargetNode.FieldLoad;
import com.oracle.svm.core.graal.nodes.ComputedIndirectCallTargetNode.FieldLoadIfZero;
import com.oracle.svm.core.graal.snippets.NonSnippetLowerings;
import com.oracle.svm.core.heap.ReferenceAccess;
import com.oracle.svm.core.heap.SubstrateReferenceMapBuilder;
import com.oracle.svm.core.meta.CompressedNullConstant;
Expand Down Expand Up @@ -200,7 +201,6 @@
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.JavaType;
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.Value;

Expand Down Expand Up @@ -669,16 +669,15 @@ protected Value emitIndirectForeignCallAddress(ForeignCallLinkage linkage) {
SubstrateForeignCallLinkage callTarget = (SubstrateForeignCallLinkage) linkage;
SharedMethod targetMethod = (SharedMethod) callTarget.getMethod();
if (SubstrateUtil.HOSTED && targetMethod.forceIndirectCall()) {
// Emit a load for the BoxedRelocatedPointer.pointer field holding the
// MethodPointer to the target method
ResolvedJavaField boxedPointerField = getMetaAccess().lookupJavaField(NonSnippetLowerings.boxedRelocatedPointerField);
int displacement = boxedPointerField.getOffset();
JavaConstant boxedPointerBase = targetMethod.getMethodPointer();
RegisterValue heapBaseRegister = ReservedRegisters.singleton().getHeapBaseRegister().asValue();
AMD64AddressValue boxedRelocatedPointerBaseAddress = new AMD64AddressValue(getLIRKindTool().getWordKind(), heapBaseRegister, Value.ILLEGAL,
Stride.S1, displacement + SubstrateAMD64Backend.addressDisplacement(boxedPointerBase, getConstantReflection()),
SubstrateAMD64Backend.addressDisplacementAnnotation(boxedPointerBase));
return getArithmetic().emitLoad(getLIRKindTool().getWordKind(), boxedRelocatedPointerBaseAddress, null, MemoryOrderMode.PLAIN, MemoryExtendKind.DEFAULT);
/*
* Load the absolute address of the target method from the method entry stored in
* the data section.
*/
CGlobalDataInfo methodDataInfo = BaseLayerMethodAccessor.singleton().getMethodData(targetMethod);
AllocatableValue methodPointerAddress = newVariable(getLIRKindTool().getWordKind());
append(new AMD64CGlobalDataLoadAddressOp(methodDataInfo, methodPointerAddress));
AMD64AddressValue methodTableEntryAddress = new AMD64AddressValue(getLIRKindTool().getWordKind(), methodPointerAddress, Value.ILLEGAL, Stride.S1, 0);
return getArithmetic().emitLoad(getLIRKindTool().getWordKind(), methodTableEntryAddress, null, MemoryOrderMode.PLAIN, MemoryExtendKind.DEFAULT);
}
if (!shouldEmitOnlyIndirectCalls()) {
return null;
Expand Down
Expand Up @@ -29,6 +29,7 @@
import static com.oracle.svm.core.graal.llvm.LLVMToolchainUtils.llvmLink;
import static com.oracle.svm.core.graal.llvm.LLVMToolchainUtils.llvmOptimize;
import static com.oracle.svm.core.graal.llvm.LLVMToolchainUtils.nativeLink;
import static com.oracle.svm.core.util.VMError.intentionallyUnimplemented;
import static com.oracle.svm.core.util.VMError.shouldNotReachHereUnexpectedInput;
import static com.oracle.svm.hosted.image.NativeImage.RWDATA_CGLOBALS_PARTITION_OFFSET;

Expand All @@ -46,11 +47,6 @@
import java.util.stream.IntStream;

import org.graalvm.collections.Pair;
import jdk.graal.compiler.code.CompilationResult;
import jdk.graal.compiler.core.common.NumUtil;
import jdk.graal.compiler.debug.DebugContext;
import jdk.graal.compiler.debug.GraalError;
import jdk.graal.compiler.debug.Indent;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;

Expand Down Expand Up @@ -78,6 +74,11 @@
import com.oracle.svm.hosted.image.RelocatableBuffer;
import com.oracle.svm.hosted.meta.HostedMethod;

import jdk.graal.compiler.code.CompilationResult;
import jdk.graal.compiler.core.common.NumUtil;
import jdk.graal.compiler.debug.DebugContext;
import jdk.graal.compiler.debug.GraalError;
import jdk.graal.compiler.debug.Indent;
import jdk.vm.ci.code.site.Call;
import jdk.vm.ci.code.site.DataPatch;
import jdk.vm.ci.code.site.DataSectionReference;
Expand Down Expand Up @@ -317,6 +318,11 @@ public void patchMethods(DebugContext debug, RelocatableBuffer relocs, ObjectFil
@Override
public NativeTextSectionImpl getTextSectionImpl(RelocatableBuffer buffer, ObjectFile objectFile, NativeImageCodeCache codeCache) {
return new NativeTextSectionImpl(buffer, objectFile, codeCache) {
@Override
protected void defineBaseLayerMethodSymbol(String name, Element section, HostedMethod method) {
throw intentionallyUnimplemented(); // ExcludeFromJacocoGeneratedReport
}

@Override
protected void defineMethodSymbol(String name, boolean global, Element section, HostedMethod method, CompilationResult result) {
ObjectFile.Symbol symbol = objectFile.createUndefinedSymbol(name, 0, true);
Expand Down
Expand Up @@ -24,6 +24,7 @@
*/
package com.oracle.svm.core;

import static com.oracle.svm.core.Containers.Options.UseContainerSupport;
import static com.oracle.svm.core.option.RuntimeOptionKey.RuntimeOptionKeyFlag.Immutable;
import static com.oracle.svm.core.option.RuntimeOptionKey.RuntimeOptionKeyFlag.RelevantForCompilationIsolates;
import static jdk.graal.compiler.core.common.SpectrePHTMitigations.None;
Expand Down Expand Up @@ -113,6 +114,12 @@ protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Boolean o
PersistImageLayerSingletons.update(values, newValue);
DeleteLocalSymbols.update(values, !newValue);
StripDebugInfo.update(values, !newValue);
InternalSymbolsAreGlobal.update(values, newValue);
AOTTrivialInline.update(values, !newValue);
if (imageLayerEnabledHandler != null) {
imageLayerEnabledHandler.onOptionEnabled(values);
}
UseContainerSupport.update(values, !newValue);
}
};

Expand Down Expand Up @@ -707,6 +714,10 @@ public static boolean useLIRBackend() {
*/
@Option(help = "Use linker option to prevent unreferenced symbols in image.")//
public static final HostedOptionKey<Boolean> RemoveUnusedSymbols = new HostedOptionKey<>(OS.getCurrent() != OS.DARWIN);
@Option(help = "Keep all undefined symbols.")//
public static final HostedOptionKey<Boolean> PreserveUndefinedSymbols = new HostedOptionKey<>(false);
@Option(help = "Ignore undefined symbols referenced from the built image.")//
public static final HostedOptionKey<Boolean> IgnoreUndefinedReferences = new HostedOptionKey<>(false);
@Option(help = "Use linker option to remove all local symbols from image.")//
public static final HostedOptionKey<Boolean> DeleteLocalSymbols = new HostedOptionKey<>(true);
@Option(help = "Compatibility option to make symbols used for the image heap global. " +
Expand Down Expand Up @@ -1133,6 +1144,10 @@ public static boolean closedTypeWorld() {
public void update(EconomicMap<OptionKey<?>, Object> values, Object boxedValue) {
super.update(values, boxedValue);
ClosedTypeWorld.update(values, false);
PreserveUndefinedSymbols.update(values, true);
/* Ignore any potential undefined references caused by inlining in base layer. */
IgnoreUndefinedReferences.update(values, true);
AOTTrivialInline.update(values, false);
if (imageLayerEnabledHandler != null) {
imageLayerEnabledHandler.onOptionEnabled(values);
}
Expand Down
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2024, 2024, 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.core.code;

import org.graalvm.nativeimage.ImageSingletons;

import com.oracle.svm.core.graal.code.CGlobalDataInfo;
import com.oracle.svm.core.meta.SharedMethod;

public interface BaseLayerMethodAccessor {
CGlobalDataInfo getMethodData(SharedMethod method);

static BaseLayerMethodAccessor singleton() {
return ImageSingletons.lookup(BaseLayerMethodAccessor.class);
}
}
Expand Up @@ -39,10 +39,13 @@
import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.c.BoxedRelocatedPointer;
import com.oracle.svm.core.code.BaseLayerMethodAccessor;
import com.oracle.svm.core.config.ConfigurationValues;
import com.oracle.svm.core.graal.code.CGlobalDataInfo;
import com.oracle.svm.core.graal.code.SubstrateBackend;
import com.oracle.svm.core.graal.meta.KnownOffsets;
import com.oracle.svm.core.graal.meta.RuntimeConfiguration;
import com.oracle.svm.core.graal.nodes.CGlobalDataLoadAddressNode;
import com.oracle.svm.core.graal.nodes.LoadOpenTypeWorldDispatchTableStartingOffset;
import com.oracle.svm.core.graal.nodes.LoweredDeadEndNode;
import com.oracle.svm.core.graal.nodes.ThrowBytecodeExceptionNode;
Expand Down Expand Up @@ -109,7 +112,6 @@
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.JavaType;
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaMethod;

public abstract class NonSnippetLowerings {
Expand Down Expand Up @@ -369,18 +371,15 @@ public void lower(FixedNode node, LoweringTool tool) {
targetMethod = implementations[0];
}

if (targetMethod.forceIndirectCall()) {
if (SubstrateUtil.HOSTED && targetMethod.forceIndirectCall()) {
/*
* Lower cross layer boundary direct calls to indirect calls. First emit a
* load for the BoxedRelocatedPointer.pointer field holding the
* MethodPointer to the target method, then emit an indirect call to that
* pointer.
* Lower cross layer boundary direct calls to indirect calls. First load the
* target method absolute address from the method entry stored in the data
* section. Then call that address indirectly.
*/
ResolvedJavaField boxedPointerField = tool.getMetaAccess().lookupJavaField(NonSnippetLowerings.boxedRelocatedPointerField);
ConstantNode boxedPointerFieldOffset = ConstantNode.forIntegerKind(ConfigurationValues.getWordKind(), boxedPointerField.getOffset(), graph);
ConstantNode boxedPointerBase = ConstantNode.forConstant(targetMethod.getMethodPointer(), tool.getMetaAccess(), graph);
CGlobalDataInfo methodDataInfo = BaseLayerMethodAccessor.singleton().getMethodData(targetMethod);
AddressNode methodPointerAddress = graph.addOrUniqueWithInputs(OffsetAddressNode.create(new CGlobalDataLoadAddressNode(methodDataInfo)));

AddressNode methodPointerAddress = graph.unique(new OffsetAddressNode(boxedPointerBase, boxedPointerFieldOffset));
/*
* Use the ANY location identity to prevent ReadNode.canonicalizeRead() to
* try to constant fold the method address.
Expand Down
Expand Up @@ -30,7 +30,6 @@
import com.oracle.svm.core.graal.code.SubstrateCallingConventionKind;
import com.oracle.svm.core.graal.code.SubstrateCallingConventionType;

import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.ResolvedJavaMethod;

/**
Expand Down Expand Up @@ -84,7 +83,4 @@ public interface SharedMethod extends ResolvedJavaMethod {

/** Always call this method indirectly, even if it is normally called directly. */
boolean forceIndirectCall();

/** Return a boxed pointer to this method. */
JavaConstant getMethodPointer();
}
Expand Up @@ -60,7 +60,6 @@
import jdk.vm.ci.meta.ConstantPool;
import jdk.vm.ci.meta.DefaultProfilingInfo;
import jdk.vm.ci.meta.ExceptionHandler;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.LineNumberTable;
import jdk.vm.ci.meta.LocalVariableTable;
import jdk.vm.ci.meta.ProfilingInfo;
Expand Down Expand Up @@ -230,11 +229,6 @@ public boolean forceIndirectCall() {
return false;
}

@Override
public JavaConstant getMethodPointer() {
throw VMError.intentionallyUnimplemented(); // ExcludeFromJacocoGeneratedReport
}

@Override
public int getEncodedGraphStartOffset() {
return encodedGraphStartOffset;
Expand Down
Expand Up @@ -1299,7 +1299,25 @@ protected NativeLibraries setupNativeLibraries(HostedProviders providers, CEnumC
if (CAnnotationProcessorCache.Options.ExitAfterCAPCache.getValue()) {
throw new InterruptImageBuilding("Exiting image generation because of " + SubstrateOptionsParser.commandArgument(CAnnotationProcessorCache.Options.ExitAfterCAPCache, "+"));
}

if (SVMImageLayerSupport.singleton().hasLoader()) {
for (Path layerPath : SVMImageLayerSupport.singleton().getLoader().getLoadPaths()) {
Path snapshotFileName = layerPath.getFileName();
if (snapshotFileName != null) {
String layerName = snapshotFileName.toString().split(ImageLayerSnapshotUtil.FILE_NAME_PREFIX)[1].split(ImageLayerSnapshotUtil.FILE_EXTENSION)[0].trim();
/*
* This currently assumes lib{layer}.so is in the same dir as the layer
* snapshot. GR-53663 will create a proper bundle that contains both files.
*/
Path layerPathDir = layerPath.getParent();
if (layerPathDir != null && layerName.startsWith("lib") && Files.exists(layerPathDir.resolve(layerName + ".so"))) {
nativeLibs.getLibraryPaths().add(layerPathDir.toString());
nativeLibs.addDynamicNonJniLibrary(layerName.split("lib")[1]);
} else {
throw VMError.shouldNotReachHere("Missing " + layerName + ".so. It must be placed in the same dir as the layer snapshot.");
}
}
}
}
return nativeLibs;
}
}
Expand Down
Expand Up @@ -52,6 +52,10 @@ public static SVMImageLayerSupport singleton() {
return ImageSingletons.lookup(SVMImageLayerSupport.class);
}

public boolean hasLoader() {
return loader != null;
}

public SVMImageLayerLoader getLoader() {
return loader;
}
Expand Down
Expand Up @@ -54,7 +54,7 @@ public enum NativeImageKind {
IMAGE_LAYER(false, true) {
@Override
public String getFilenameSuffix() {
return ".gso"; // Graal shared object
return ".so";
}
},
SHARED_LIBRARY(false) {
Expand Down

0 comments on commit 69d3c62

Please sign in to comment.