HotSpotForeignCallsProviderImpl.java revision 12651:6ef01bd40ce2
14887Schin/*
24887Schin * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
34887Schin * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
410898Sroland.mainz@nrubsig.org *
54887Schin * This code is free software; you can redistribute it and/or modify it
64887Schin * under the terms of the GNU General Public License version 2 only, as
78462SApril.Chin@Sun.COM * published by the Free Software Foundation.
84887Schin *
94887Schin * This code is distributed in the hope that it will be useful, but WITHOUT
104887Schin * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
114887Schin * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
124887Schin * version 2 for more details (a copy is included in the LICENSE file that
134887Schin * accompanied this code).
144887Schin *
154887Schin * You should have received a copy of the GNU General Public License version
164887Schin * 2 along with this work; if not, write to the Free Software Foundation,
174887Schin * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
184887Schin *
194887Schin * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
204887Schin * or visit www.oracle.com if you need additional information or have any
214887Schin * questions.
224887Schin */
234887Schinpackage org.graalvm.compiler.hotspot.meta;
244887Schin
254887Schinimport static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS;
264887Schinimport static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.SAFEPOINT;
274887Schinimport static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCall;
284887Schinimport static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCallee;
294887Schin
304887Schinimport java.util.HashMap;
314887Schinimport java.util.Map;
324887Schin
334887Schinimport org.graalvm.compiler.core.common.LIRKind;
344887Schinimport org.graalvm.compiler.core.common.LocationIdentity;
354887Schinimport org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
364887Schinimport org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
374887Schinimport org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect;
384887Schinimport org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition;
394887Schinimport org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl;
404887Schinimport org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
414887Schinimport org.graalvm.compiler.hotspot.stubs.ForeignCallStub;
424887Schinimport org.graalvm.compiler.hotspot.stubs.Stub;
434887Schinimport org.graalvm.compiler.word.Word;
444887Schinimport org.graalvm.compiler.word.WordTypes;
454887Schin
464887Schinimport jdk.vm.ci.code.CallingConvention;
474887Schinimport jdk.vm.ci.code.CodeCacheProvider;
484887Schinimport jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider;
494887Schinimport jdk.vm.ci.meta.JavaKind;
504887Schinimport jdk.vm.ci.meta.MetaAccessProvider;
514887Schin
524887Schin/**
534887Schin * HotSpot implementation of {@link HotSpotForeignCallsProvider}.
544887Schin */
554887Schinpublic abstract class HotSpotForeignCallsProviderImpl implements HotSpotForeignCallsProvider {
564887Schin
574887Schin    public static final ForeignCallDescriptor OSR_MIGRATION_END = new ForeignCallDescriptor("OSR_migration_end", void.class, long.class);
584887Schin    public static final ForeignCallDescriptor IDENTITY_HASHCODE = new ForeignCallDescriptor("identity_hashcode", int.class, Object.class);
594887Schin    public static final ForeignCallDescriptor VERIFY_OOP = new ForeignCallDescriptor("verify_oop", Object.class, Object.class);
604887Schin    public static final ForeignCallDescriptor LOAD_AND_CLEAR_EXCEPTION = new ForeignCallDescriptor("load_and_clear_exception", Object.class, Word.class);
614887Schin
624887Schin    public static final ForeignCallDescriptor TEST_DEOPTIMIZE_CALL_INT = new ForeignCallDescriptor("test_deoptimize_call_int", int.class, int.class);
634887Schin
644887Schin    protected final HotSpotJVMCIRuntimeProvider jvmciRuntime;
654887Schin    protected final HotSpotGraalRuntimeProvider runtime;
664887Schin
674887Schin    protected final Map<ForeignCallDescriptor, HotSpotForeignCallLinkage> foreignCalls = new HashMap<>();
684887Schin    protected final MetaAccessProvider metaAccess;
694887Schin    protected final CodeCacheProvider codeCache;
704887Schin    protected final WordTypes wordTypes;
714887Schin
724887Schin    public HotSpotForeignCallsProviderImpl(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, CodeCacheProvider codeCache,
734887Schin                    WordTypes wordTypes) {
744887Schin        this.jvmciRuntime = jvmciRuntime;
754887Schin        this.runtime = runtime;
764887Schin        this.metaAccess = metaAccess;
774887Schin        this.codeCache = codeCache;
784887Schin        this.wordTypes = wordTypes;
794887Schin    }
804887Schin
814887Schin    /**
824887Schin     * Registers the linkage for a foreign call.
834887Schin     */
844887Schin    public HotSpotForeignCallLinkage register(HotSpotForeignCallLinkage linkage) {
854887Schin        assert !foreignCalls.containsKey(linkage.getDescriptor()) : "already registered linkage for " + linkage.getDescriptor();
864887Schin        foreignCalls.put(linkage.getDescriptor(), linkage);
874887Schin        return linkage;
884887Schin    }
894887Schin
904887Schin    /**
914887Schin     * Return true if the descriptor has already been registered.
924887Schin     */
934887Schin    public boolean isRegistered(ForeignCallDescriptor descriptor) {
944887Schin        return foreignCalls.containsKey(descriptor);
954887Schin    }
964887Schin
974887Schin    /**
984887Schin     * Creates and registers the details for linking a foreign call to a {@link Stub}.
994887Schin     *
1004887Schin     * @param descriptor the signature of the call to the stub
1014887Schin     * @param reexecutable specifies if the stub call can be re-executed without (meaningful) side
1024887Schin     *            effects. Deoptimization will not return to a point before a stub call that cannot
1034887Schin     *            be re-executed.
1044887Schin     * @param transition specifies if this is a {@linkplain Transition#LEAF leaf} call
1054887Schin     * @param killedLocations the memory locations killed by the stub call
1064887Schin     */
1074887Schin    public HotSpotForeignCallLinkage registerStubCall(ForeignCallDescriptor descriptor, boolean reexecutable, Transition transition, LocationIdentity... killedLocations) {
1084887Schin        return register(HotSpotForeignCallLinkageImpl.create(metaAccess, codeCache, wordTypes, this, descriptor, 0L, PRESERVES_REGISTERS, JavaCall, JavaCallee, transition, reexecutable,
1094887Schin                        killedLocations));
1104887Schin    }
1114887Schin
1124887Schin    /**
1134887Schin     * Creates and registers the linkage for a foreign call.
1144887Schin     *
1154887Schin     * @param descriptor the signature of the foreign call
1164887Schin     * @param address the address of the code to call
1174887Schin     * @param outgoingCcType outgoing (caller) calling convention type
1184887Schin     * @param effect specifies if the call destroys or preserves all registers (apart from
1194887Schin     *            temporaries which are always destroyed)
1204887Schin     * @param transition specifies if this is a {@linkplain Transition#LEAF leaf} call
1214887Schin     * @param reexecutable specifies if the foreign call can be re-executed without (meaningful)
1224887Schin     *            side effects. Deoptimization will not return to a point before a foreign call that
1234887Schin     *            cannot be re-executed.
1244887Schin     * @param killedLocations the memory locations killed by the foreign call
1254887Schin     */
1264887Schin    public HotSpotForeignCallLinkage registerForeignCall(ForeignCallDescriptor descriptor, long address, CallingConvention.Type outgoingCcType, RegisterEffect effect, Transition transition,
1274887Schin                    boolean reexecutable, LocationIdentity... killedLocations) {
1284887Schin        Class<?> resultType = descriptor.getResultType();
1294887Schin        assert address != 0;
1304887Schin        assert transition != SAFEPOINT || resultType.isPrimitive() || Word.class.isAssignableFrom(resultType) : "non-leaf foreign calls must return objects in thread local storage: " + descriptor;
1314887Schin        return register(HotSpotForeignCallLinkageImpl.create(metaAccess, codeCache, wordTypes, this, descriptor, address, effect, outgoingCcType, null, transition, reexecutable, killedLocations));
1324887Schin    }
1334887Schin
1344887Schin    /**
1354887Schin     * Creates a {@linkplain ForeignCallStub stub} for a foreign call.
1364887Schin     *
1374887Schin     * @param descriptor the signature of the call to the stub
1384887Schin     * @param address the address of the foreign code to call
1394887Schin     * @param prependThread true if the JavaThread value for the current thread is to be prepended
1404887Schin     *            to the arguments for the call to {@code address}
1414887Schin     * @param transition specifies if this is a {@linkplain Transition#LEAF leaf} call
1424887Schin     * @param reexecutable specifies if the foreign call can be re-executed without (meaningful)
1434887Schin     *            side effects. Deoptimization will not return to a point before a foreign call that
1444887Schin     *            cannot be re-executed.
1454887Schin     * @param killedLocations the memory locations killed by the foreign call
1464887Schin     */
1474887Schin    public void linkForeignCall(HotSpotProviders providers, ForeignCallDescriptor descriptor, long address, boolean prependThread, Transition transition, boolean reexecutable,
1484887Schin                    LocationIdentity... killedLocations) {
1494887Schin        ForeignCallStub stub = new ForeignCallStub(jvmciRuntime, providers, address, descriptor, prependThread, transition, reexecutable, killedLocations);
1504887Schin        HotSpotForeignCallLinkage linkage = stub.getLinkage();
1514887Schin        HotSpotForeignCallLinkage targetLinkage = stub.getTargetLinkage();
1524887Schin        linkage.setCompiledStub(stub);
1534887Schin        register(linkage);
1544887Schin        register(targetLinkage);
1554887Schin    }
1564887Schin
1574887Schin    public static final boolean PREPEND_THREAD = true;
1584887Schin    public static final boolean DONT_PREPEND_THREAD = !PREPEND_THREAD;
1594887Schin
1604887Schin    public static final boolean REEXECUTABLE = true;
1614887Schin    public static final boolean NOT_REEXECUTABLE = !REEXECUTABLE;
1624887Schin
1634887Schin    public static final LocationIdentity[] NO_LOCATIONS = {};
1644887Schin
1654887Schin    @Override
1664887Schin    public HotSpotForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) {
1674887Schin        assert foreignCalls != null : descriptor;
1684887Schin        HotSpotForeignCallLinkage callTarget = foreignCalls.get(descriptor);
1694887Schin        callTarget.finalizeAddress(runtime.getHostBackend());
1704887Schin        return callTarget;
1714887Schin    }
1724887Schin
1734887Schin    @Override
1744887Schin    public boolean isReexecutable(ForeignCallDescriptor descriptor) {
1754887Schin        assert foreignCalls.containsKey(descriptor) : "unknown foreign call: " + descriptor;
1764887Schin        return foreignCalls.get(descriptor).isReexecutable();
1774887Schin    }
1784887Schin
1794887Schin    @Override
1804887Schin    public boolean canDeoptimize(ForeignCallDescriptor descriptor) {
1814887Schin        assert foreignCalls.containsKey(descriptor) : "unknown foreign call: " + descriptor;
1824887Schin        return foreignCalls.get(descriptor).needsDebugInfo();
1834887Schin    }
1844887Schin
1854887Schin    @Override
1864887Schin    public boolean isGuaranteedSafepoint(ForeignCallDescriptor descriptor) {
1874887Schin        assert foreignCalls.containsKey(descriptor) : "unknown foreign call: " + descriptor;
1884887Schin        return foreignCalls.get(descriptor).isGuaranteedSafepoint();
1894887Schin    }
1904887Schin
1914887Schin    @Override
1924887Schin    public LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor) {
1934887Schin        assert foreignCalls.containsKey(descriptor) : "unknown foreign call: " + descriptor;
1944887Schin        return foreignCalls.get(descriptor).getKilledLocations();
1954887Schin    }
1964887Schin
1974887Schin    @Override
1984887Schin    public LIRKind getValueKind(JavaKind javaKind) {
1994887Schin        return LIRKind.fromJavaKind(codeCache.getTarget().arch, javaKind);
2004887Schin    }
2014887Schin}
2024887Schin