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