5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.hotspot.meta; 24 25 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; 26 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.SAFEPOINT; 27 import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCall; 28 import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCallee; 29 30 import java.util.HashMap; 31 import java.util.Map; 32 33 import org.graalvm.compiler.core.common.LIRKind; 34 import org.graalvm.compiler.core.common.LocationIdentity; 35 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; 36 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; 37 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect; 38 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition; 39 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl; 40 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; 41 import org.graalvm.compiler.hotspot.stubs.ForeignCallStub; 42 import org.graalvm.compiler.hotspot.stubs.Stub; 43 import org.graalvm.compiler.word.Word; 44 import org.graalvm.compiler.word.WordTypes; 45 46 import jdk.vm.ci.code.CallingConvention; 47 import jdk.vm.ci.code.CodeCacheProvider; 48 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; 49 import jdk.vm.ci.meta.JavaKind; 50 import jdk.vm.ci.meta.MetaAccessProvider; 51 52 /** 53 * HotSpot implementation of {@link HotSpotForeignCallsProvider}. 54 */ 55 public abstract class HotSpotForeignCallsProviderImpl implements HotSpotForeignCallsProvider { 56 57 public static final ForeignCallDescriptor OSR_MIGRATION_END = new ForeignCallDescriptor("OSR_migration_end", void.class, long.class); 58 public static final ForeignCallDescriptor IDENTITY_HASHCODE = new ForeignCallDescriptor("identity_hashcode", int.class, Object.class); 59 public static final ForeignCallDescriptor VERIFY_OOP = new ForeignCallDescriptor("verify_oop", Object.class, Object.class); 60 public static final ForeignCallDescriptor LOAD_AND_CLEAR_EXCEPTION = new ForeignCallDescriptor("load_and_clear_exception", Object.class, Word.class); 61 62 public static final ForeignCallDescriptor TEST_DEOPTIMIZE_CALL_INT = new ForeignCallDescriptor("test_deoptimize_call_int", int.class, int.class); 63 64 protected final HotSpotJVMCIRuntimeProvider jvmciRuntime; 65 protected final HotSpotGraalRuntimeProvider runtime; 66 67 protected final Map<ForeignCallDescriptor, HotSpotForeignCallLinkage> foreignCalls = new HashMap<>(); 68 protected final MetaAccessProvider metaAccess; 69 protected final CodeCacheProvider codeCache; 70 protected final WordTypes wordTypes; 71 72 public HotSpotForeignCallsProviderImpl(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, CodeCacheProvider codeCache, 73 WordTypes wordTypes) { 74 this.jvmciRuntime = jvmciRuntime; 75 this.runtime = runtime; 76 this.metaAccess = metaAccess; 77 this.codeCache = codeCache; 78 this.wordTypes = wordTypes; 79 } 80 81 /** 82 * Registers the linkage for a foreign call. 83 */ 84 public HotSpotForeignCallLinkage register(HotSpotForeignCallLinkage linkage) { 85 assert !foreignCalls.containsKey(linkage.getDescriptor()) : "already registered linkage for " + linkage.getDescriptor(); 86 foreignCalls.put(linkage.getDescriptor(), linkage); 87 return linkage; 127 boolean reexecutable, LocationIdentity... killedLocations) { 128 Class<?> resultType = descriptor.getResultType(); 129 assert address != 0; 130 assert transition != SAFEPOINT || resultType.isPrimitive() || Word.class.isAssignableFrom(resultType) : "non-leaf foreign calls must return objects in thread local storage: " + descriptor; 131 return register(HotSpotForeignCallLinkageImpl.create(metaAccess, codeCache, wordTypes, this, descriptor, address, effect, outgoingCcType, null, transition, reexecutable, killedLocations)); 132 } 133 134 /** 135 * Creates a {@linkplain ForeignCallStub stub} for a foreign call. 136 * 137 * @param descriptor the signature of the call to the stub 138 * @param address the address of the foreign code to call 139 * @param prependThread true if the JavaThread value for the current thread is to be prepended 140 * to the arguments for the call to {@code address} 141 * @param transition specifies if this is a {@linkplain Transition#LEAF leaf} call 142 * @param reexecutable specifies if the foreign call can be re-executed without (meaningful) 143 * side effects. Deoptimization will not return to a point before a foreign call that 144 * cannot be re-executed. 145 * @param killedLocations the memory locations killed by the foreign call 146 */ 147 public void linkForeignCall(HotSpotProviders providers, ForeignCallDescriptor descriptor, long address, boolean prependThread, Transition transition, boolean reexecutable, 148 LocationIdentity... killedLocations) { 149 ForeignCallStub stub = new ForeignCallStub(jvmciRuntime, providers, address, descriptor, prependThread, transition, reexecutable, killedLocations); 150 HotSpotForeignCallLinkage linkage = stub.getLinkage(); 151 HotSpotForeignCallLinkage targetLinkage = stub.getTargetLinkage(); 152 linkage.setCompiledStub(stub); 153 register(linkage); 154 register(targetLinkage); 155 } 156 157 public static final boolean PREPEND_THREAD = true; 158 public static final boolean DONT_PREPEND_THREAD = !PREPEND_THREAD; 159 160 public static final boolean REEXECUTABLE = true; 161 public static final boolean NOT_REEXECUTABLE = !REEXECUTABLE; 162 163 public static final LocationIdentity[] NO_LOCATIONS = {}; 164 165 @Override 166 public HotSpotForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) { 167 assert foreignCalls != null : descriptor; 168 HotSpotForeignCallLinkage callTarget = foreignCalls.get(descriptor); 169 callTarget.finalizeAddress(runtime.getHostBackend()); 181 assert foreignCalls.containsKey(descriptor) : "unknown foreign call: " + descriptor; 182 return foreignCalls.get(descriptor).needsDebugInfo(); 183 } 184 185 @Override 186 public boolean isGuaranteedSafepoint(ForeignCallDescriptor descriptor) { 187 assert foreignCalls.containsKey(descriptor) : "unknown foreign call: " + descriptor; 188 return foreignCalls.get(descriptor).isGuaranteedSafepoint(); 189 } 190 191 @Override 192 public LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor) { 193 assert foreignCalls.containsKey(descriptor) : "unknown foreign call: " + descriptor; 194 return foreignCalls.get(descriptor).getKilledLocations(); 195 } 196 197 @Override 198 public LIRKind getValueKind(JavaKind javaKind) { 199 return LIRKind.fromJavaKind(codeCache.getTarget().arch, javaKind); 200 } 201 } | 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.hotspot.meta; 24 25 import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCall; 26 import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCallee; 27 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; 28 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.SAFEPOINT; 29 30 import java.util.ArrayList; 31 import java.util.List; 32 33 import org.graalvm.compiler.core.common.LIRKind; 34 import org.graalvm.compiler.core.common.LocationIdentity; 35 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; 36 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; 37 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect; 38 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition; 39 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl; 40 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; 41 import org.graalvm.compiler.hotspot.stubs.ForeignCallStub; 42 import org.graalvm.compiler.hotspot.stubs.Stub; 43 import org.graalvm.compiler.options.OptionValues; 44 import org.graalvm.compiler.word.Word; 45 import org.graalvm.compiler.word.WordTypes; 46 import org.graalvm.util.EconomicMap; 47 48 import jdk.vm.ci.code.CallingConvention; 49 import jdk.vm.ci.code.CodeCacheProvider; 50 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; 51 import jdk.vm.ci.meta.JavaKind; 52 import jdk.vm.ci.meta.MetaAccessProvider; 53 54 /** 55 * HotSpot implementation of {@link HotSpotForeignCallsProvider}. 56 */ 57 public abstract class HotSpotForeignCallsProviderImpl implements HotSpotForeignCallsProvider { 58 59 public static final ForeignCallDescriptor OSR_MIGRATION_END = new ForeignCallDescriptor("OSR_migration_end", void.class, long.class); 60 public static final ForeignCallDescriptor IDENTITY_HASHCODE = new ForeignCallDescriptor("identity_hashcode", int.class, Object.class); 61 public static final ForeignCallDescriptor VERIFY_OOP = new ForeignCallDescriptor("verify_oop", Object.class, Object.class); 62 public static final ForeignCallDescriptor LOAD_AND_CLEAR_EXCEPTION = new ForeignCallDescriptor("load_and_clear_exception", Object.class, Word.class); 63 64 public static final ForeignCallDescriptor TEST_DEOPTIMIZE_CALL_INT = new ForeignCallDescriptor("test_deoptimize_call_int", int.class, int.class); 65 66 protected final HotSpotJVMCIRuntimeProvider jvmciRuntime; 67 protected final HotSpotGraalRuntimeProvider runtime; 68 69 protected final EconomicMap<ForeignCallDescriptor, HotSpotForeignCallLinkage> foreignCalls = EconomicMap.create(); 70 protected final MetaAccessProvider metaAccess; 71 protected final CodeCacheProvider codeCache; 72 protected final WordTypes wordTypes; 73 74 public HotSpotForeignCallsProviderImpl(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, CodeCacheProvider codeCache, 75 WordTypes wordTypes) { 76 this.jvmciRuntime = jvmciRuntime; 77 this.runtime = runtime; 78 this.metaAccess = metaAccess; 79 this.codeCache = codeCache; 80 this.wordTypes = wordTypes; 81 } 82 83 /** 84 * Registers the linkage for a foreign call. 85 */ 86 public HotSpotForeignCallLinkage register(HotSpotForeignCallLinkage linkage) { 87 assert !foreignCalls.containsKey(linkage.getDescriptor()) : "already registered linkage for " + linkage.getDescriptor(); 88 foreignCalls.put(linkage.getDescriptor(), linkage); 89 return linkage; 129 boolean reexecutable, LocationIdentity... killedLocations) { 130 Class<?> resultType = descriptor.getResultType(); 131 assert address != 0; 132 assert transition != SAFEPOINT || resultType.isPrimitive() || Word.class.isAssignableFrom(resultType) : "non-leaf foreign calls must return objects in thread local storage: " + descriptor; 133 return register(HotSpotForeignCallLinkageImpl.create(metaAccess, codeCache, wordTypes, this, descriptor, address, effect, outgoingCcType, null, transition, reexecutable, killedLocations)); 134 } 135 136 /** 137 * Creates a {@linkplain ForeignCallStub stub} for a foreign call. 138 * 139 * @param descriptor the signature of the call to the stub 140 * @param address the address of the foreign code to call 141 * @param prependThread true if the JavaThread value for the current thread is to be prepended 142 * to the arguments for the call to {@code address} 143 * @param transition specifies if this is a {@linkplain Transition#LEAF leaf} call 144 * @param reexecutable specifies if the foreign call can be re-executed without (meaningful) 145 * side effects. Deoptimization will not return to a point before a foreign call that 146 * cannot be re-executed. 147 * @param killedLocations the memory locations killed by the foreign call 148 */ 149 public void linkForeignCall(OptionValues options, HotSpotProviders providers, ForeignCallDescriptor descriptor, long address, boolean prependThread, Transition transition, 150 boolean reexecutable, LocationIdentity... killedLocations) { 151 ForeignCallStub stub = new ForeignCallStub(options, jvmciRuntime, providers, address, descriptor, prependThread, transition, reexecutable, killedLocations); 152 HotSpotForeignCallLinkage linkage = stub.getLinkage(); 153 HotSpotForeignCallLinkage targetLinkage = stub.getTargetLinkage(); 154 linkage.setCompiledStub(stub); 155 register(linkage); 156 register(targetLinkage); 157 } 158 159 public static final boolean PREPEND_THREAD = true; 160 public static final boolean DONT_PREPEND_THREAD = !PREPEND_THREAD; 161 162 public static final boolean REEXECUTABLE = true; 163 public static final boolean NOT_REEXECUTABLE = !REEXECUTABLE; 164 165 public static final LocationIdentity[] NO_LOCATIONS = {}; 166 167 @Override 168 public HotSpotForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) { 169 assert foreignCalls != null : descriptor; 170 HotSpotForeignCallLinkage callTarget = foreignCalls.get(descriptor); 171 callTarget.finalizeAddress(runtime.getHostBackend()); 183 assert foreignCalls.containsKey(descriptor) : "unknown foreign call: " + descriptor; 184 return foreignCalls.get(descriptor).needsDebugInfo(); 185 } 186 187 @Override 188 public boolean isGuaranteedSafepoint(ForeignCallDescriptor descriptor) { 189 assert foreignCalls.containsKey(descriptor) : "unknown foreign call: " + descriptor; 190 return foreignCalls.get(descriptor).isGuaranteedSafepoint(); 191 } 192 193 @Override 194 public LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor) { 195 assert foreignCalls.containsKey(descriptor) : "unknown foreign call: " + descriptor; 196 return foreignCalls.get(descriptor).getKilledLocations(); 197 } 198 199 @Override 200 public LIRKind getValueKind(JavaKind javaKind) { 201 return LIRKind.fromJavaKind(codeCache.getTarget().arch, javaKind); 202 } 203 204 @Override 205 public List<Stub> getStubs() { 206 List<Stub> stubs = new ArrayList<>(); 207 for (HotSpotForeignCallLinkage linkage : foreignCalls.getValues()) { 208 if (linkage.isCompiledStub()) { 209 Stub stub = linkage.getStub(); 210 assert stub != null; 211 stubs.add(stub); 212 } 213 } 214 return stubs; 215 } 216 } |