8215224: Update Graal
Reviewed-by: kvn
This commit is contained in:
parent
13b56530f4
commit
8d8b784c9e
@ -333,8 +333,7 @@ final class AOTCompiledClass {
|
||||
AOTKlassData data = klassData.get(name);
|
||||
if (data != null) {
|
||||
HotSpotResolvedObjectType oldType = data.getType();
|
||||
assert oldType == type : "duplicate classes for name " + type.getName() + ", fingerprints old: " + oldType.getFingerprint() + ", new: " + type.getFingerprint() +
|
||||
", klass pointers old: " + oldType.klass() + ", new: " + type.klass();
|
||||
assert oldType.equals(type) : "duplicate classes for name " + type.getName();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
@ -60,20 +60,6 @@ public interface SnippetReflectionProvider {
|
||||
*/
|
||||
<T> T asObject(Class<T> type, JavaConstant constant);
|
||||
|
||||
/**
|
||||
* Gets the object reference a given constant represents if it is of a given type. The constant
|
||||
* must have kind {@link JavaKind#Object}.
|
||||
*
|
||||
* @param type the expected type of the object represented by {@code constant}. If the object is
|
||||
* required to be of this type, then wrap the call to this method in
|
||||
* {@link Objects#requireNonNull(Object)}.
|
||||
* @param constant an object constant
|
||||
* @return the object value represented by {@code constant} if it is an
|
||||
* {@link ResolvedJavaType#isInstance(JavaConstant) instance of} {@code type} otherwise
|
||||
* {@code null}
|
||||
*/
|
||||
Object asObject(ResolvedJavaType type, JavaConstant constant);
|
||||
|
||||
/**
|
||||
* Creates a boxed constant for the given kind from an Object. The object needs to be of the
|
||||
* Java boxed type corresponding to the kind.
|
||||
@ -82,7 +68,13 @@ public interface SnippetReflectionProvider {
|
||||
* @param value the Java boxed value: a {@link Byte} instance for {@link JavaKind#Byte}, etc.
|
||||
* @return the boxed copy of {@code value}
|
||||
*/
|
||||
JavaConstant forBoxed(JavaKind kind, Object value);
|
||||
default JavaConstant forBoxed(JavaKind kind, Object value) {
|
||||
if (kind == JavaKind.Object) {
|
||||
return forObject(value);
|
||||
} else {
|
||||
return JavaConstant.forBoxedPrimitive(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value to bind to an injected parameter in a node intrinsic.
|
||||
@ -97,7 +89,8 @@ public interface SnippetReflectionProvider {
|
||||
* Get the original Java class corresponding to a {@link ResolvedJavaType}.
|
||||
*
|
||||
* @param type the type for which the original Java class is requested
|
||||
* @return the original Java class corresponding to the {@code type} parameter
|
||||
* @return the original Java class corresponding to {@code type} or {@code null} if this object
|
||||
* cannot map {@link ResolvedJavaType} instances to {@link Class} instances
|
||||
*/
|
||||
Class<?> originalClass(ResolvedJavaType type);
|
||||
}
|
||||
|
@ -326,7 +326,7 @@ public class Fields {
|
||||
|
||||
public void appendFields(StringBuilder sb) {
|
||||
for (int i = 0; i < offsets.length; i++) {
|
||||
sb.append(i == 0 ? "" : ", ").append(getName(i)).append('@').append(offsets[i]);
|
||||
sb.append(i == 0 ? "" : ", ").append(getDeclaringClass(i).getSimpleName()).append('.').append(getName(i)).append('@').append(offsets[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
package org.graalvm.compiler.core.common.spi;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.options.Option;
|
||||
import org.graalvm.compiler.options.OptionKey;
|
||||
@ -46,9 +48,26 @@ public abstract class JavaConstantFieldProvider implements ConstantFieldProvider
|
||||
|
||||
protected JavaConstantFieldProvider(MetaAccessProvider metaAccess) {
|
||||
try {
|
||||
this.stringValueField = metaAccess.lookupJavaField(String.class.getDeclaredField("value"));
|
||||
this.stringHashField = metaAccess.lookupJavaField(String.class.getDeclaredField("hash"));
|
||||
} catch (NoSuchFieldException | SecurityException e) {
|
||||
ResolvedJavaType stringType = metaAccess.lookupJavaType(String.class);
|
||||
ResolvedJavaField[] stringFields = stringType.getInstanceFields(false);
|
||||
ResolvedJavaField valueField = null;
|
||||
ResolvedJavaField hashField = null;
|
||||
for (ResolvedJavaField field : stringFields) {
|
||||
if (field.getName().equals("value")) {
|
||||
valueField = field;
|
||||
} else if (field.getName().equals("hash")) {
|
||||
hashField = field;
|
||||
}
|
||||
}
|
||||
if (valueField == null) {
|
||||
throw new GraalError("missing field value " + Arrays.toString(stringFields));
|
||||
}
|
||||
if (hashField == null) {
|
||||
throw new GraalError("missing field hash " + Arrays.toString(stringFields));
|
||||
}
|
||||
stringValueField = valueField;
|
||||
stringHashField = hashField;
|
||||
} catch (SecurityException e) {
|
||||
throw new GraalError(e);
|
||||
}
|
||||
}
|
||||
|
@ -31,9 +31,12 @@ import org.graalvm.compiler.api.replacements.Snippet;
|
||||
import org.graalvm.compiler.asm.amd64.AMD64Address;
|
||||
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
|
||||
import org.graalvm.compiler.bytecode.BytecodeProvider;
|
||||
import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||
import org.graalvm.compiler.core.common.LIRKind;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
|
||||
import org.graalvm.compiler.core.common.type.DataPointerConstant;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.hotspot.HotSpotBackend;
|
||||
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
|
||||
@ -46,6 +49,7 @@ import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
|
||||
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
|
||||
import org.graalvm.compiler.lir.jtt.LIRTest;
|
||||
import org.graalvm.compiler.lir.jtt.LIRTestSpecification;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.extended.ForeignCallNode;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
|
||||
@ -67,7 +71,6 @@ import jdk.vm.ci.meta.AllocatableValue;
|
||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import jdk.vm.ci.meta.Value;
|
||||
import org.graalvm.compiler.hotspot.HotSpotBackend;
|
||||
|
||||
public class StubAVXTest extends LIRTest {
|
||||
|
||||
@ -183,10 +186,16 @@ public class StubAVXTest extends LIRTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BytecodeProvider getReplacementsBytecodeProvider() {
|
||||
protected void registerSnippet() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StructuredGraph buildInitialGraph(DebugContext debug, CompilationIdentifier compilationId, Object[] args) {
|
||||
// Build the snippet graph directly since snippet registration is closed at this point.
|
||||
ReplacementsImpl d = (ReplacementsImpl) providers.getReplacements();
|
||||
MetaAccessProvider metaAccess = d.providers.getMetaAccess();
|
||||
return new ClassfileBytecodeProvider(metaAccess, d.snippetReflection, ClassLoader.getSystemClassLoader());
|
||||
MetaAccessProvider metaAccess = d.getProviders().getMetaAccess();
|
||||
BytecodeProvider bytecodes = new ClassfileBytecodeProvider(metaAccess, d.snippetReflection, ClassLoader.getSystemClassLoader());
|
||||
return d.makeGraph(debug, bytecodes, method, args, null, false, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,6 +150,7 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory {
|
||||
providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers,
|
||||
snippetReflection, wordTypes,
|
||||
plugins);
|
||||
replacements.setProviders(providers);
|
||||
}
|
||||
try (InitTimer rt = timer("instantiate backend")) {
|
||||
return createBackend(config, graalRuntime, providers);
|
||||
|
@ -410,7 +410,6 @@ public class CheckGraalIntrinsics extends GraalTest {
|
||||
"java/lang/StringLatin1.compareToUTF16([B[B)I",
|
||||
"java/lang/StringUTF16.compareTo([B[B)I",
|
||||
"java/lang/StringUTF16.compareToLatin1([B[B)I",
|
||||
"java/lang/Thread.onSpinWait()V",
|
||||
"jdk/internal/misc/Unsafe.getAndAddInt(Ljava/lang/Object;JI)I",
|
||||
"jdk/internal/misc/Unsafe.getAndAddLong(Ljava/lang/Object;JJ)J",
|
||||
"jdk/internal/misc/Unsafe.getAndSetInt(Ljava/lang/Object;JI)I",
|
||||
@ -418,6 +417,7 @@ public class CheckGraalIntrinsics extends GraalTest {
|
||||
"jdk/internal/misc/Unsafe.getAndSet" + oopName + "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;");
|
||||
}
|
||||
add(toBeInvestigated,
|
||||
"java/lang/Thread.onSpinWait()V",
|
||||
"jdk/internal/misc/Unsafe.getCharUnaligned(Ljava/lang/Object;J)C",
|
||||
"jdk/internal/misc/Unsafe.getIntUnaligned(Ljava/lang/Object;J)I",
|
||||
"jdk/internal/misc/Unsafe.getLongUnaligned(Ljava/lang/Object;J)J",
|
||||
|
@ -55,6 +55,11 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest {
|
||||
public int hashCode() {
|
||||
return clazz.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Wrapper-" + clazz;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -24,13 +24,14 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.test;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.config;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.referentOffset;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.Fold;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase;
|
||||
import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.nodes.G1ReferentFieldReadBarrier;
|
||||
@ -38,6 +39,8 @@ import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;
|
||||
import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType;
|
||||
import org.graalvm.compiler.nodes.memory.ReadNode;
|
||||
import org.graalvm.compiler.nodes.memory.WriteNode;
|
||||
@ -51,6 +54,7 @@ import org.graalvm.compiler.phases.common.inlining.InliningPhase;
|
||||
import org.graalvm.compiler.phases.common.inlining.policy.InlineEverythingPolicy;
|
||||
import org.graalvm.compiler.phases.tiers.HighTierContext;
|
||||
import org.graalvm.compiler.phases.tiers.MidTierContext;
|
||||
import org.graalvm.compiler.replacements.NodeIntrinsificationProvider;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -71,7 +75,6 @@ import sun.misc.Unsafe;
|
||||
public class WriteBarrierAdditionTest extends HotSpotGraalCompilerTest {
|
||||
|
||||
private final GraalHotSpotVMConfig config = runtime().getVMConfig();
|
||||
private static final long referentOffset = referentOffset();
|
||||
|
||||
public static class Container {
|
||||
|
||||
@ -167,8 +170,20 @@ public class WriteBarrierAdditionTest extends HotSpotGraalCompilerTest {
|
||||
testHelper("test5Snippet", config.useG1GC ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) {
|
||||
NodeIntrinsicPluginFactory.InjectionProvider injection = new NodeIntrinsificationProvider(getMetaAccess(), getSnippetReflection(), getProviders().getForeignCalls(), null);
|
||||
new PluginFactory_WriteBarrierAdditionTest().registerPlugins(invocationPlugins, injection);
|
||||
super.registerInvocationPlugins(invocationPlugins);
|
||||
}
|
||||
|
||||
@Fold
|
||||
public static boolean useCompressedOops(@Fold.InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.useCompressedOops;
|
||||
}
|
||||
|
||||
public static Object test5Snippet() throws Exception {
|
||||
return UNSAFE.getObject(wr, config(null).useCompressedOops ? 12L : 16L);
|
||||
return UNSAFE.getObject(wr, useCompressedOops(GraalHotSpotVMConfigBase.INJECTED_VMCONFIG) ? 12L : 16L);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -177,7 +192,7 @@ public class WriteBarrierAdditionTest extends HotSpotGraalCompilerTest {
|
||||
*/
|
||||
@Test
|
||||
public void test6() throws Exception {
|
||||
test2("testUnsafeLoad", UNSAFE, wr, Long.valueOf(referentOffset), null);
|
||||
test2("testUnsafeLoad", UNSAFE, wr, Long.valueOf(referentOffset(getMetaAccess())), null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -186,7 +201,7 @@ public class WriteBarrierAdditionTest extends HotSpotGraalCompilerTest {
|
||||
*/
|
||||
@Test
|
||||
public void test7() throws Exception {
|
||||
test2("testUnsafeLoad", UNSAFE, con, Long.valueOf(referentOffset), null);
|
||||
test2("testUnsafeLoad", UNSAFE, con, Long.valueOf(referentOffset(getMetaAccess())), null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -299,7 +314,7 @@ public class WriteBarrierAdditionTest extends HotSpotGraalCompilerTest {
|
||||
Assert.assertTrue(read.getAddress() instanceof OffsetAddressNode);
|
||||
JavaConstant constDisp = ((OffsetAddressNode) read.getAddress()).getOffset().asJavaConstant();
|
||||
Assert.assertNotNull(constDisp);
|
||||
Assert.assertEquals(referentOffset, constDisp.asLong());
|
||||
Assert.assertEquals(referentOffset(getMetaAccess()), constDisp.asLong());
|
||||
Assert.assertTrue(config.useG1GC);
|
||||
Assert.assertEquals(BarrierType.PRECISE, read.getBarrierType());
|
||||
Assert.assertTrue(read.next() instanceof G1ReferentFieldReadBarrier);
|
||||
|
@ -29,6 +29,8 @@ import java.lang.reflect.Modifier;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.Fold;
|
||||
import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
|
||||
import jdk.vm.ci.common.JVMCIError;
|
||||
import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
|
||||
@ -71,6 +73,8 @@ public abstract class GraalHotSpotVMConfigBase extends HotSpotVMConfigAccess {
|
||||
*/
|
||||
public static final GraalHotSpotVMConfig INJECTED_VMCONFIG = null;
|
||||
public static final MetaAccessProvider INJECTED_METAACCESS = null;
|
||||
public static final OptionValues INJECTED_OPTIONVALUES = null;
|
||||
public static final IntrinsicContext INJECTED_INTRINSIC_CONTEXT = null;
|
||||
|
||||
public final String osName = getHostOSName();
|
||||
public final String osArch = getHostArchitectureName();
|
||||
|
@ -36,8 +36,6 @@ import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.Stream.Builder;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.MethodSubstitution;
|
||||
import org.graalvm.compiler.api.replacements.Snippet;
|
||||
@ -113,13 +111,13 @@ public class HotSpotCompiledCodeBuilder {
|
||||
byte[] dataSection = new byte[data.getSectionSize()];
|
||||
|
||||
ByteBuffer buffer = ByteBuffer.wrap(dataSection).order(ByteOrder.nativeOrder());
|
||||
Builder<DataPatch> patchBuilder = Stream.builder();
|
||||
List<DataPatch> patches = new ArrayList<>();
|
||||
data.buildDataSection(buffer, (position, vmConstant) -> {
|
||||
patchBuilder.accept(new DataPatch(position, new ConstantReference(vmConstant)));
|
||||
patches.add(new DataPatch(position, new ConstantReference(vmConstant)));
|
||||
});
|
||||
|
||||
int dataSectionAlignment = data.getSectionAlignment();
|
||||
DataPatch[] dataSectionPatches = patchBuilder.build().toArray(len -> new DataPatch[len]);
|
||||
DataPatch[] dataSectionPatches = patches.toArray(new DataPatch[patches.size()]);
|
||||
|
||||
int totalFrameSize = compResult.getTotalFrameSize();
|
||||
StackSlot customStackArea = compResult.getCustomStackArea();
|
||||
|
@ -45,6 +45,7 @@ import org.graalvm.compiler.api.runtime.GraalRuntime;
|
||||
import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
|
||||
import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||
import org.graalvm.compiler.core.common.GraalOptions;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
|
||||
import org.graalvm.compiler.core.target.Backend;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DebugContext.Description;
|
||||
@ -328,8 +329,12 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
|
||||
return (T) this;
|
||||
} else if (clazz == SnippetReflectionProvider.class) {
|
||||
return (T) getHostProviders().getSnippetReflection();
|
||||
} else if (clazz == GraalHotSpotVMConfig.class) {
|
||||
return (T) getVMConfig();
|
||||
} else if (clazz == StampProvider.class) {
|
||||
return (T) getHostProviders().getStampProvider();
|
||||
} else if (ForeignCallsProvider.class.isAssignableFrom(clazz)) {
|
||||
return (T) getHostProviders().getForeignCalls();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -92,6 +92,7 @@ public abstract class HotSpotHostBackend extends HotSpotBackend {
|
||||
Iterable<DebugHandlersFactory> factories = Collections.singletonList(new GraalDebugHandlersFactory(providers.getSnippetReflection()));
|
||||
lowerer.initialize(options, factories, providers, config);
|
||||
}
|
||||
providers.getReplacements().closeSnippetRegistration();
|
||||
}
|
||||
|
||||
protected CallingConvention makeCallingConvention(StructuredGraph graph, Stub stub) {
|
||||
|
@ -26,7 +26,9 @@ package org.graalvm.compiler.hotspot;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
|
||||
import org.graalvm.compiler.bytecode.BytecodeProvider;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotWordOperationPlugin;
|
||||
import org.graalvm.compiler.hotspot.word.HotSpotOperation;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.phases.util.Providers;
|
||||
import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
|
||||
@ -40,13 +42,25 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
* them.
|
||||
*/
|
||||
public class HotSpotReplacementsImpl extends ReplacementsImpl {
|
||||
|
||||
public HotSpotReplacementsImpl(OptionValues options, Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) {
|
||||
super(options, new GraalDebugHandlersFactory(snippetReflection), providers, snippetReflection, bytecodeProvider, target);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasGenericInvocationPluginAnnotation(ResolvedJavaMethod method) {
|
||||
return method.getAnnotation(HotSpotOperation.class) != null || super.hasGenericInvocationPluginAnnotation(method);
|
||||
public Class<? extends GraphBuilderPlugin> getIntrinsifyingPlugin(ResolvedJavaMethod method) {
|
||||
return method.getAnnotation(HotSpotOperation.class) != null ? HotSpotWordOperationPlugin.class : super.getIntrinsifyingPlugin(method);
|
||||
}
|
||||
|
||||
private boolean snippetRegistrationClosed;
|
||||
|
||||
@Override
|
||||
public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) {
|
||||
assert !snippetRegistrationClosed;
|
||||
super.registerSnippet(method, original, receiver, trackNodeSourcePosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeSnippetRegistration() {
|
||||
snippetRegistrationClosed = true;
|
||||
}
|
||||
}
|
||||
|
@ -59,14 +59,11 @@ import org.graalvm.compiler.graph.NodeInputList;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
|
||||
import org.graalvm.compiler.hotspot.nodes.BeginLockScopeNode;
|
||||
import org.graalvm.compiler.hotspot.replacements.arraycopy.HotSpotArraycopySnippets;
|
||||
import org.graalvm.compiler.nodes.ComputeObjectAddressNode;
|
||||
import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePostWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePreWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.nodes.G1ReferentFieldReadBarrier;
|
||||
import org.graalvm.compiler.nodes.GetObjectAddressNode;
|
||||
import org.graalvm.compiler.hotspot.nodes.HotSpotCompressionNode;
|
||||
import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode;
|
||||
import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode;
|
||||
@ -90,20 +87,22 @@ import org.graalvm.compiler.hotspot.replacements.KlassLayoutHelperNode;
|
||||
import org.graalvm.compiler.hotspot.replacements.LoadExceptionObjectSnippets;
|
||||
import org.graalvm.compiler.hotspot.replacements.MonitorSnippets;
|
||||
import org.graalvm.compiler.hotspot.replacements.NewObjectSnippets;
|
||||
import org.graalvm.compiler.hotspot.replacements.ObjectCloneSnippets;
|
||||
import org.graalvm.compiler.hotspot.replacements.StringToBytesSnippets;
|
||||
import org.graalvm.compiler.hotspot.replacements.UnsafeLoadSnippets;
|
||||
import org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets;
|
||||
import org.graalvm.compiler.hotspot.replacements.aot.ResolveConstantSnippets;
|
||||
import org.graalvm.compiler.replacements.arraycopy.ArrayCopyNode;
|
||||
import org.graalvm.compiler.replacements.arraycopy.ArrayCopySnippets;
|
||||
import org.graalvm.compiler.replacements.arraycopy.ArrayCopyWithSlowPathNode;
|
||||
import org.graalvm.compiler.hotspot.replacements.arraycopy.HotSpotArraycopySnippets;
|
||||
import org.graalvm.compiler.hotspot.replacements.profiling.ProfileSnippets;
|
||||
import org.graalvm.compiler.hotspot.stubs.ForeignCallSnippets;
|
||||
import org.graalvm.compiler.hotspot.word.KlassPointer;
|
||||
import org.graalvm.compiler.nodes.AbstractBeginNode;
|
||||
import org.graalvm.compiler.nodes.AbstractDeoptimizeNode;
|
||||
import org.graalvm.compiler.nodes.CompressionNode.CompressionOp;
|
||||
import org.graalvm.compiler.nodes.ComputeObjectAddressNode;
|
||||
import org.graalvm.compiler.nodes.ConstantNode;
|
||||
import org.graalvm.compiler.nodes.FixedNode;
|
||||
import org.graalvm.compiler.nodes.GetObjectAddressNode;
|
||||
import org.graalvm.compiler.nodes.Invoke;
|
||||
import org.graalvm.compiler.nodes.LogicNode;
|
||||
import org.graalvm.compiler.nodes.LoweredCallTargetNode;
|
||||
@ -159,6 +158,9 @@ import org.graalvm.compiler.nodes.type.StampTool;
|
||||
import org.graalvm.compiler.nodes.util.GraphUtil;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.replacements.DefaultJavaLoweringProvider;
|
||||
import org.graalvm.compiler.replacements.arraycopy.ArrayCopyNode;
|
||||
import org.graalvm.compiler.replacements.arraycopy.ArrayCopySnippets;
|
||||
import org.graalvm.compiler.replacements.arraycopy.ArrayCopyWithSlowPathNode;
|
||||
import org.graalvm.compiler.replacements.nodes.AssertionNode;
|
||||
import jdk.internal.vm.compiler.word.LocationIdentity;
|
||||
|
||||
@ -196,6 +198,9 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider
|
||||
protected ResolveConstantSnippets.Templates resolveConstantSnippets;
|
||||
protected ProfileSnippets.Templates profileSnippets;
|
||||
|
||||
protected ObjectCloneSnippets.Templates objectCloneSnippets;
|
||||
protected ForeignCallSnippets.Templates foreignCallSnippets;
|
||||
|
||||
public DefaultHotSpotLoweringProvider(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers,
|
||||
HotSpotConstantReflectionProvider constantReflection, TargetDescription target) {
|
||||
super(metaAccess, foreignCalls, target, runtime.getVMConfig().useCompressedOops);
|
||||
@ -221,6 +226,8 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider
|
||||
hashCodeSnippets = new HashCodeSnippets.Templates(options, factories, providers, target);
|
||||
resolveConstantSnippets = new ResolveConstantSnippets.Templates(options, factories, providers, target);
|
||||
profileSnippets = new ProfileSnippets.Templates(options, factories, providers, target);
|
||||
objectCloneSnippets = new ObjectCloneSnippets.Templates(options, factories, providers, target);
|
||||
foreignCallSnippets = new ForeignCallSnippets.Templates(options, factories, providers, target);
|
||||
}
|
||||
|
||||
public MonitorSnippets.Templates getMonitorSnippets() {
|
||||
@ -286,7 +293,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider
|
||||
} else if (n instanceof DynamicNewInstanceNode) {
|
||||
DynamicNewInstanceNode newInstanceNode = (DynamicNewInstanceNode) n;
|
||||
if (newInstanceNode.getClassClass() == null) {
|
||||
JavaConstant classClassMirror = constantReflection.forObject(Class.class);
|
||||
JavaConstant classClassMirror = constantReflection.asJavaClass(metaAccess.lookupJavaType(Class.class));
|
||||
ConstantNode classClass = ConstantNode.forConstant(classClassMirror, tool.getMetaAccess(), graph);
|
||||
newInstanceNode.setClassClass(classClass);
|
||||
}
|
||||
@ -300,7 +307,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider
|
||||
} else if (n instanceof DynamicNewArrayNode) {
|
||||
DynamicNewArrayNode dynamicNewArrayNode = (DynamicNewArrayNode) n;
|
||||
if (dynamicNewArrayNode.getVoidClass() == null) {
|
||||
JavaConstant voidClassMirror = constantReflection.forObject(void.class);
|
||||
JavaConstant voidClassMirror = constantReflection.asJavaClass(metaAccess.lookupJavaType(void.class));
|
||||
ConstantNode voidClass = ConstantNode.forConstant(voidClassMirror, tool.getMetaAccess(), graph);
|
||||
dynamicNewArrayNode.setVoidClass(voidClass);
|
||||
}
|
||||
@ -770,8 +777,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider
|
||||
|
||||
@Override
|
||||
public int fieldOffset(ResolvedJavaField f) {
|
||||
HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) f;
|
||||
return field.getOffset();
|
||||
return f.getOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -783,4 +789,14 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider
|
||||
protected final JavaKind getStorageKind(ResolvedJavaField field) {
|
||||
return field.getJavaKind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectCloneSnippets.Templates getObjectCloneSnippets() {
|
||||
return objectCloneSnippets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForeignCallSnippets.Templates getForeignCallSnippets() {
|
||||
return foreignCallSnippets;
|
||||
}
|
||||
}
|
||||
|
@ -34,8 +34,6 @@ import java.lang.invoke.ConstantCallSite;
|
||||
import java.lang.invoke.MutableCallSite;
|
||||
import java.lang.invoke.VolatileCallSite;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.math.BigInteger;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
@ -45,7 +43,6 @@ import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
|
||||
import org.graalvm.compiler.core.common.type.ObjectStamp;
|
||||
import org.graalvm.compiler.core.common.type.StampFactory;
|
||||
import org.graalvm.compiler.core.common.type.TypeReference;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.hotspot.nodes.CurrentJavaThreadNode;
|
||||
import org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions;
|
||||
@ -66,7 +63,6 @@ import org.graalvm.compiler.hotspot.replacements.SHA2Substitutions;
|
||||
import org.graalvm.compiler.hotspot.replacements.SHA5Substitutions;
|
||||
import org.graalvm.compiler.hotspot.replacements.SHASubstitutions;
|
||||
import org.graalvm.compiler.hotspot.replacements.ThreadSubstitutions;
|
||||
import org.graalvm.compiler.replacements.arraycopy.ArrayCopyNode;
|
||||
import org.graalvm.compiler.hotspot.word.HotSpotWordTypes;
|
||||
import org.graalvm.compiler.nodes.ConstantNode;
|
||||
import org.graalvm.compiler.nodes.NamedLocationIdentity;
|
||||
@ -95,6 +91,7 @@ import org.graalvm.compiler.replacements.MethodHandlePlugin;
|
||||
import org.graalvm.compiler.replacements.NodeIntrinsificationProvider;
|
||||
import org.graalvm.compiler.replacements.ReplacementsImpl;
|
||||
import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins;
|
||||
import org.graalvm.compiler.replacements.arraycopy.ArrayCopyNode;
|
||||
import org.graalvm.compiler.serviceprovider.GraalServices;
|
||||
import org.graalvm.compiler.word.WordOperationPlugin;
|
||||
import org.graalvm.compiler.word.WordTypes;
|
||||
@ -458,18 +455,8 @@ public class HotSpotGraphBuilderPlugins {
|
||||
if (config.useMultiplyToLenIntrinsic()) {
|
||||
assert config.multiplyToLen != 0L;
|
||||
if (Java8OrEarlier) {
|
||||
try {
|
||||
Method m = BigInteger.class.getDeclaredMethod("multiplyToLen", int[].class, int.class, int[].class, int.class, int[].class);
|
||||
if (Modifier.isStatic(m.getModifiers())) {
|
||||
r.registerMethodSubstitution(BigIntegerSubstitutions.class, "multiplyToLen", "multiplyToLenStatic", int[].class, int.class, int[].class, int.class,
|
||||
int[].class);
|
||||
} else {
|
||||
r.registerMethodSubstitution(BigIntegerSubstitutions.class, "multiplyToLen", Receiver.class, int[].class, int.class, int[].class, int.class,
|
||||
int[].class);
|
||||
}
|
||||
} catch (NoSuchMethodException | SecurityException e) {
|
||||
throw new GraalError(e);
|
||||
}
|
||||
r.registerMethodSubstitution(BigIntegerSubstitutions.class, "multiplyToLen", "multiplyToLenStatic", int[].class, int.class, int[].class, int.class,
|
||||
int[].class);
|
||||
} else {
|
||||
r.registerMethodSubstitution(BigIntegerSubstitutions.class, "implMultiplyToLen", "multiplyToLenStatic", int[].class, int.class, int[].class, int.class,
|
||||
int[].class);
|
||||
|
@ -26,6 +26,8 @@ package org.graalvm.compiler.hotspot.meta;
|
||||
|
||||
import org.graalvm.compiler.debug.DebugHandlersFactory;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.hotspot.replacements.ObjectCloneSnippets;
|
||||
import org.graalvm.compiler.hotspot.stubs.ForeignCallSnippets;
|
||||
import org.graalvm.compiler.nodes.spi.LoweringProvider;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
|
||||
@ -35,4 +37,8 @@ import org.graalvm.compiler.options.OptionValues;
|
||||
public interface HotSpotLoweringProvider extends LoweringProvider {
|
||||
|
||||
void initialize(OptionValues options, Iterable<DebugHandlersFactory> factories, HotSpotProviders providers, GraalHotSpotVMConfig config);
|
||||
|
||||
ObjectCloneSnippets.Templates getObjectCloneSnippets();
|
||||
|
||||
ForeignCallSnippets.Templates getForeignCallSnippets();
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ package org.graalvm.compiler.hotspot.meta;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
|
||||
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
|
||||
import org.graalvm.compiler.hotspot.word.HotSpotWordTypes;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
|
||||
import org.graalvm.compiler.nodes.spi.LoweringProvider;
|
||||
@ -33,6 +34,7 @@ import org.graalvm.compiler.nodes.spi.Replacements;
|
||||
import org.graalvm.compiler.phases.tiers.SuitesProvider;
|
||||
import org.graalvm.compiler.phases.util.Providers;
|
||||
|
||||
import jdk.vm.ci.code.CodeCacheProvider;
|
||||
import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
|
||||
import jdk.vm.ci.meta.ConstantReflectionProvider;
|
||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
@ -90,4 +92,53 @@ public class HotSpotProviders extends Providers {
|
||||
public HotSpotWordTypes getWordTypes() {
|
||||
return wordTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Providers copyWith(MetaAccessProvider substitution) {
|
||||
return new HotSpotProviders(substitution, getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getSuites(),
|
||||
getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Providers copyWith(CodeCacheProvider substitution) {
|
||||
return new HotSpotProviders(getMetaAccess(), (HotSpotCodeCacheProvider) substitution, getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(),
|
||||
getSuites(),
|
||||
getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Providers copyWith(ConstantReflectionProvider substitution) {
|
||||
return new HotSpotProviders(getMetaAccess(), getCodeCache(), substitution, getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getSuites(),
|
||||
getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Providers copyWith(ConstantFieldProvider substitution) {
|
||||
return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), substitution, getForeignCalls(), getLowerer(), getReplacements(), getSuites(),
|
||||
getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Providers copyWith(ForeignCallsProvider substitution) {
|
||||
return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), (HotSpotForeignCallsProvider) substitution, getLowerer(), getReplacements(),
|
||||
getSuites(),
|
||||
getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Providers copyWith(LoweringProvider substitution) {
|
||||
return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), substitution, getReplacements(), getSuites(),
|
||||
getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Providers copyWith(Replacements substitution) {
|
||||
return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), substitution, getSuites(),
|
||||
getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
|
||||
}
|
||||
|
||||
public Providers copyWith(Plugins substitution) {
|
||||
return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getSuites(),
|
||||
getRegisters(), getSnippetReflection(), getWordTypes(), substitution);
|
||||
}
|
||||
}
|
||||
|
@ -54,22 +54,16 @@ public class HotSpotSnippetReflectionProvider implements SnippetReflectionProvid
|
||||
return constantReflection.forObject(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object asObject(ResolvedJavaType type, JavaConstant constant) {
|
||||
if (constant.isNull()) {
|
||||
return null;
|
||||
}
|
||||
HotSpotObjectConstant hsConstant = (HotSpotObjectConstant) constant;
|
||||
return hsConstant.asObject(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T asObject(Class<T> type, JavaConstant constant) {
|
||||
if (constant.isNull()) {
|
||||
return null;
|
||||
}
|
||||
HotSpotObjectConstant hsConstant = (HotSpotObjectConstant) constant;
|
||||
return hsConstant.asObject(type);
|
||||
if (constant instanceof HotSpotObjectConstant) {
|
||||
HotSpotObjectConstant hsConstant = (HotSpotObjectConstant) constant;
|
||||
return hsConstant.asObject(type);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -66,7 +66,7 @@ import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
* Extends {@link WordOperationPlugin} to handle {@linkplain HotSpotOperation HotSpot word
|
||||
* operations}.
|
||||
*/
|
||||
class HotSpotWordOperationPlugin extends WordOperationPlugin {
|
||||
public class HotSpotWordOperationPlugin extends WordOperationPlugin {
|
||||
HotSpotWordOperationPlugin(SnippetReflectionProvider snippetReflection, WordTypes wordTypes) {
|
||||
super(snippetReflection, wordTypes);
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
|
||||
import org.graalvm.compiler.nodes.spi.LIRLowerable;
|
||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
||||
import org.graalvm.compiler.nodes.util.GraphUtil;
|
||||
import org.graalvm.compiler.word.Word;
|
||||
import jdk.internal.vm.compiler.word.LocationIdentity;
|
||||
|
||||
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
|
||||
@ -70,7 +71,7 @@ public class InitializeKlassStubCall extends AbstractMemoryCheckpoint implements
|
||||
}
|
||||
|
||||
@NodeIntrinsic
|
||||
public static native KlassPointer initializeKlass(KlassPointer value, Object string);
|
||||
public static native KlassPointer initializeKlass(KlassPointer value, Word string);
|
||||
|
||||
@Override
|
||||
public Node canonical(CanonicalizerTool tool) {
|
||||
|
@ -43,6 +43,7 @@ import org.graalvm.compiler.nodes.ValueNode;
|
||||
import org.graalvm.compiler.nodes.spi.LIRLowerable;
|
||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
||||
import org.graalvm.compiler.nodes.util.GraphUtil;
|
||||
import org.graalvm.compiler.word.Word;
|
||||
|
||||
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
|
||||
import jdk.vm.ci.hotspot.HotSpotObjectConstant;
|
||||
@ -79,10 +80,10 @@ public class ResolveConstantStubCall extends DeoptimizingStubCall implements Can
|
||||
public static native Object resolveObject(Object value, Object symbol);
|
||||
|
||||
@NodeIntrinsic
|
||||
public static native KlassPointer resolveKlass(KlassPointer value, Object symbol);
|
||||
public static native KlassPointer resolveKlass(KlassPointer value, Word symbol);
|
||||
|
||||
@NodeIntrinsic
|
||||
public static native KlassPointer resolveKlass(KlassPointer value, Object symbol, @ConstantNodeParameter HotSpotConstantLoadAction action);
|
||||
public static native KlassPointer resolveKlass(KlassPointer value, Word symbol, @ConstantNodeParameter HotSpotConstantLoadAction action);
|
||||
|
||||
@Override
|
||||
public Node canonical(CanonicalizerTool tool) {
|
||||
|
@ -43,6 +43,7 @@ import org.graalvm.compiler.nodes.ValueNode;
|
||||
import org.graalvm.compiler.nodes.spi.LIRLowerable;
|
||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
||||
import org.graalvm.compiler.nodes.util.GraphUtil;
|
||||
import org.graalvm.compiler.word.Word;
|
||||
|
||||
import jdk.vm.ci.meta.Constant;
|
||||
import jdk.vm.ci.meta.Value;
|
||||
@ -67,7 +68,7 @@ public class ResolveMethodAndLoadCountersStubCall extends DeoptimizingStubCall i
|
||||
}
|
||||
|
||||
@NodeIntrinsic
|
||||
public static native MethodCountersPointer resolveMethodAndLoadCounters(MethodPointer method, KlassPointer klassHint, Object methodDescription);
|
||||
public static native MethodCountersPointer resolveMethodAndLoadCounters(MethodPointer method, KlassPointer klassHint, Word methodDescription);
|
||||
|
||||
@Override
|
||||
public Node canonical(CanonicalizerTool tool) {
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.phases;
|
||||
|
||||
import static jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
|
||||
import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required;
|
||||
|
||||
import org.graalvm.compiler.core.common.PermanentBailoutException;
|
||||
@ -77,6 +76,7 @@ import jdk.vm.ci.meta.DeoptimizationAction;
|
||||
import jdk.vm.ci.meta.DeoptimizationReason;
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.SpeculationLog;
|
||||
import jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
|
||||
import jdk.vm.ci.runtime.JVMCICompiler;
|
||||
|
||||
public class OnStackReplacementPhase extends Phase {
|
||||
|
@ -24,18 +24,20 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.replacements;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_INTRINSIC_CONTEXT;
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_BLOCK;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_BLOCK_WITH_ORIGINAL_KEY;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.ENCRYPT_BLOCK;
|
||||
import static org.graalvm.compiler.hotspot.replacements.CipherBlockChainingSubstitutions.aesCryptType;
|
||||
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.VERY_SLOW_PATH_PROBABILITY;
|
||||
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
|
||||
import static org.graalvm.compiler.replacements.ReplacementsUtil.getArrayBaseOffset;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.ClassSubstitution;
|
||||
import org.graalvm.compiler.api.replacements.Fold;
|
||||
import org.graalvm.compiler.api.replacements.MethodSubstitution;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
|
||||
import org.graalvm.compiler.graph.Node.NodeIntrinsic;
|
||||
import org.graalvm.compiler.nodes.ComputeObjectAddressNode;
|
||||
@ -43,6 +45,7 @@ import org.graalvm.compiler.nodes.DeoptimizeNode;
|
||||
import org.graalvm.compiler.nodes.PiNode;
|
||||
import org.graalvm.compiler.nodes.extended.ForeignCallNode;
|
||||
import org.graalvm.compiler.nodes.extended.RawLoadNode;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
|
||||
import org.graalvm.compiler.word.Word;
|
||||
import jdk.internal.vm.compiler.word.LocationIdentity;
|
||||
import jdk.internal.vm.compiler.word.Pointer;
|
||||
@ -60,28 +63,20 @@ import jdk.vm.ci.meta.JavaKind;
|
||||
@ClassSubstitution(className = "com.sun.crypto.provider.AESCrypt", optional = true)
|
||||
public class AESCryptSubstitutions {
|
||||
|
||||
static final long kOffset;
|
||||
static final long lastKeyOffset;
|
||||
static final Class<?> AESCryptClass;
|
||||
|
||||
/**
|
||||
* The AES block size is a constant 128 bits as defined by the
|
||||
* <a href="http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197.pdf">standard<a/>.
|
||||
*/
|
||||
static final int AES_BLOCK_SIZE_IN_BYTES = 16;
|
||||
|
||||
static {
|
||||
try {
|
||||
// Need to use the system class loader as com.sun.crypto.provider.AESCrypt
|
||||
// is normally loaded by the extension class loader which is not delegated
|
||||
// to by the JVMCI class loader.
|
||||
ClassLoader cl = ClassLoader.getSystemClassLoader();
|
||||
AESCryptClass = Class.forName("com.sun.crypto.provider.AESCrypt", true, cl);
|
||||
kOffset = UnsafeAccess.UNSAFE.objectFieldOffset(AESCryptClass.getDeclaredField("K"));
|
||||
lastKeyOffset = UnsafeAccess.UNSAFE.objectFieldOffset(AESCryptClass.getDeclaredField("lastKey"));
|
||||
} catch (Exception ex) {
|
||||
throw new GraalError(ex);
|
||||
}
|
||||
@Fold
|
||||
static long kOffset(@Fold.InjectedParameter IntrinsicContext context) {
|
||||
return HotSpotReplacementsUtil.getFieldOffset(aesCryptType(context), "K");
|
||||
}
|
||||
|
||||
@Fold
|
||||
static long lastKeyOffset(@Fold.InjectedParameter IntrinsicContext context) {
|
||||
return HotSpotReplacementsUtil.getFieldOffset(aesCryptType(context), "lastKey");
|
||||
}
|
||||
|
||||
@MethodSubstitution(isStatic = false)
|
||||
@ -123,8 +118,8 @@ public class AESCryptSubstitutions {
|
||||
|
||||
private static void crypt(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset, boolean encrypt, boolean withOriginalKey) {
|
||||
checkArgs(in, inOffset, out, outOffset);
|
||||
Object realReceiver = PiNode.piCastNonNull(rcvr, AESCryptClass);
|
||||
Object kObject = RawLoadNode.load(realReceiver, kOffset, JavaKind.Object, LocationIdentity.any());
|
||||
Object realReceiver = PiNode.piCastNonNull(rcvr, aesCryptType(INJECTED_INTRINSIC_CONTEXT));
|
||||
Object kObject = RawLoadNode.load(realReceiver, kOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
|
||||
Pointer kAddr = Word.objectToTrackedPointer(kObject).add(getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Int));
|
||||
Word inAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(in, getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte) + inOffset));
|
||||
Word outAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(out, getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte) + outOffset));
|
||||
@ -132,7 +127,7 @@ public class AESCryptSubstitutions {
|
||||
encryptBlockStub(ENCRYPT_BLOCK, inAddr, outAddr, kAddr);
|
||||
} else {
|
||||
if (withOriginalKey) {
|
||||
Object lastKeyObject = RawLoadNode.load(realReceiver, lastKeyOffset, JavaKind.Object, LocationIdentity.any());
|
||||
Object lastKeyObject = RawLoadNode.load(realReceiver, lastKeyOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
|
||||
Pointer lastKeyAddr = Word.objectToTrackedPointer(lastKeyObject).add(getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte));
|
||||
decryptBlockWithOriginalKeyStub(DECRYPT_BLOCK_WITH_ORIGINAL_KEY, inAddr, outAddr, kAddr, lastKeyAddr);
|
||||
} else {
|
||||
|
@ -24,23 +24,24 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.replacements;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_METAACCESS;
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_INTRINSIC_CONTEXT;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_WITH_ORIGINAL_KEY;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.ENCRYPT;
|
||||
import static org.graalvm.compiler.hotspot.replacements.UnsafeAccess.UNSAFE;
|
||||
import static org.graalvm.compiler.nodes.PiNode.piCastNonNull;
|
||||
import static org.graalvm.compiler.nodes.java.InstanceOfNode.doInstanceof;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.ClassSubstitution;
|
||||
import org.graalvm.compiler.api.replacements.Fold;
|
||||
import org.graalvm.compiler.api.replacements.MethodSubstitution;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
|
||||
import org.graalvm.compiler.graph.Node.NodeIntrinsic;
|
||||
import org.graalvm.compiler.nodes.ComputeObjectAddressNode;
|
||||
import org.graalvm.compiler.nodes.PiNode;
|
||||
import org.graalvm.compiler.nodes.extended.ForeignCallNode;
|
||||
import org.graalvm.compiler.nodes.extended.RawLoadNode;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
|
||||
import org.graalvm.compiler.replacements.ReplacementsUtil;
|
||||
import org.graalvm.compiler.word.Word;
|
||||
import jdk.internal.vm.compiler.word.LocationIdentity;
|
||||
@ -48,6 +49,7 @@ import jdk.internal.vm.compiler.word.Pointer;
|
||||
import jdk.internal.vm.compiler.word.WordFactory;
|
||||
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
|
||||
// JaCoCo Exclude
|
||||
|
||||
@ -57,38 +59,17 @@ import jdk.vm.ci.meta.JavaKind;
|
||||
@ClassSubstitution(className = "com.sun.crypto.provider.CipherBlockChaining", optional = true)
|
||||
public class CipherBlockChainingSubstitutions {
|
||||
|
||||
private static final long embeddedCipherOffset;
|
||||
private static final long rOffset;
|
||||
private static final Class<?> cipherBlockChainingClass;
|
||||
private static final Class<?> feedbackCipherClass;
|
||||
static {
|
||||
try {
|
||||
// Need to use the system class loader as com.sun.crypto.provider.FeedbackCipher
|
||||
// is normally loaded by the extension class loader which is not delegated
|
||||
// to by the JVMCI class loader.
|
||||
ClassLoader cl = ClassLoader.getSystemClassLoader();
|
||||
|
||||
feedbackCipherClass = Class.forName("com.sun.crypto.provider.FeedbackCipher", true, cl);
|
||||
embeddedCipherOffset = UNSAFE.objectFieldOffset(feedbackCipherClass.getDeclaredField("embeddedCipher"));
|
||||
|
||||
cipherBlockChainingClass = Class.forName("com.sun.crypto.provider.CipherBlockChaining", true, cl);
|
||||
rOffset = UNSAFE.objectFieldOffset(cipherBlockChainingClass.getDeclaredField("r"));
|
||||
} catch (Exception ex) {
|
||||
throw new GraalError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Fold
|
||||
static Class<?> getAESCryptClass() {
|
||||
return AESCryptSubstitutions.AESCryptClass;
|
||||
static ResolvedJavaType aesCryptType(@Fold.InjectedParameter IntrinsicContext context) {
|
||||
return HotSpotReplacementsUtil.getType(context, "Lcom/sun/crypto/provider/AESCrypt;");
|
||||
}
|
||||
|
||||
@MethodSubstitution(isStatic = false)
|
||||
static int encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
|
||||
Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
|
||||
Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
|
||||
if (getAESCryptClass().isInstance(embeddedCipher)) {
|
||||
Object aesCipher = getAESCryptClass().cast(embeddedCipher);
|
||||
Object realReceiver = piCastNonNull(rcvr, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT));
|
||||
Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
|
||||
if (doInstanceof(aesCryptType(INJECTED_INTRINSIC_CONTEXT), embeddedCipher)) {
|
||||
Object aesCipher = piCastNonNull(embeddedCipher, aesCryptType(INJECTED_INTRINSIC_CONTEXT));
|
||||
crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true, false);
|
||||
return inLength;
|
||||
} else {
|
||||
@ -96,12 +77,22 @@ public class CipherBlockChainingSubstitutions {
|
||||
}
|
||||
}
|
||||
|
||||
@Fold
|
||||
static long embeddedCipherOffset(@Fold.InjectedParameter IntrinsicContext context) {
|
||||
return HotSpotReplacementsUtil.getFieldOffset(HotSpotReplacementsUtil.getType(context, "Lcom/sun/crypto/provider/FeedbackCipher;"), "embeddedCipher");
|
||||
}
|
||||
|
||||
@Fold
|
||||
static long rOffset(@Fold.InjectedParameter IntrinsicContext intrinsicContext) {
|
||||
return HotSpotReplacementsUtil.getFieldOffset(HotSpotReplacementsUtil.methodHolderClass(intrinsicContext), "r");
|
||||
}
|
||||
|
||||
@MethodSubstitution(isStatic = false, value = "implEncrypt")
|
||||
static int implEncrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
|
||||
Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
|
||||
Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
|
||||
if (getAESCryptClass().isInstance(embeddedCipher)) {
|
||||
Object aesCipher = getAESCryptClass().cast(embeddedCipher);
|
||||
Object realReceiver = piCastNonNull(rcvr, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT));
|
||||
Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
|
||||
if (doInstanceof(aesCryptType(INJECTED_INTRINSIC_CONTEXT), embeddedCipher)) {
|
||||
Object aesCipher = piCastNonNull(embeddedCipher, aesCryptType(INJECTED_INTRINSIC_CONTEXT));
|
||||
crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true, false);
|
||||
return inLength;
|
||||
} else {
|
||||
@ -111,10 +102,10 @@ public class CipherBlockChainingSubstitutions {
|
||||
|
||||
@MethodSubstitution(isStatic = false)
|
||||
static int decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
|
||||
Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
|
||||
Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
|
||||
if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
|
||||
Object aesCipher = getAESCryptClass().cast(embeddedCipher);
|
||||
Object realReceiver = piCastNonNull(rcvr, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT));
|
||||
Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
|
||||
if (in != out && doInstanceof(aesCryptType(INJECTED_INTRINSIC_CONTEXT), embeddedCipher)) {
|
||||
Object aesCipher = piCastNonNull(embeddedCipher, aesCryptType(INJECTED_INTRINSIC_CONTEXT));
|
||||
crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, false);
|
||||
return inLength;
|
||||
} else {
|
||||
@ -124,10 +115,10 @@ public class CipherBlockChainingSubstitutions {
|
||||
|
||||
@MethodSubstitution(isStatic = false)
|
||||
static int implDecrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
|
||||
Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
|
||||
Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
|
||||
if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
|
||||
Object aesCipher = getAESCryptClass().cast(embeddedCipher);
|
||||
Object realReceiver = piCastNonNull(rcvr, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT));
|
||||
Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
|
||||
if (in != out && doInstanceof(aesCryptType(INJECTED_INTRINSIC_CONTEXT), embeddedCipher)) {
|
||||
Object aesCipher = piCastNonNull(embeddedCipher, aesCryptType(INJECTED_INTRINSIC_CONTEXT));
|
||||
crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, false);
|
||||
return inLength;
|
||||
} else {
|
||||
@ -141,10 +132,10 @@ public class CipherBlockChainingSubstitutions {
|
||||
*/
|
||||
@MethodSubstitution(isStatic = false, value = "decrypt")
|
||||
static int decryptWithOriginalKey(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
|
||||
Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
|
||||
Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
|
||||
if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
|
||||
Object aesCipher = getAESCryptClass().cast(embeddedCipher);
|
||||
Object realReceiver = piCastNonNull(rcvr, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT));
|
||||
Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
|
||||
if (in != out && doInstanceof(aesCryptType(INJECTED_INTRINSIC_CONTEXT), embeddedCipher)) {
|
||||
Object aesCipher = piCastNonNull(embeddedCipher, aesCryptType(INJECTED_INTRINSIC_CONTEXT));
|
||||
crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, true);
|
||||
return inLength;
|
||||
} else {
|
||||
@ -157,10 +148,10 @@ public class CipherBlockChainingSubstitutions {
|
||||
*/
|
||||
@MethodSubstitution(isStatic = false, value = "implDecrypt")
|
||||
static int implDecryptWithOriginalKey(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
|
||||
Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
|
||||
Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
|
||||
if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
|
||||
Object aesCipher = getAESCryptClass().cast(embeddedCipher);
|
||||
Object realReceiver = piCastNonNull(rcvr, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT));
|
||||
Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
|
||||
if (in != out && doInstanceof(aesCryptType(INJECTED_INTRINSIC_CONTEXT), embeddedCipher)) {
|
||||
Object aesCipher = piCastNonNull(embeddedCipher, aesCryptType(INJECTED_INTRINSIC_CONTEXT));
|
||||
crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, true);
|
||||
return inLength;
|
||||
} else {
|
||||
@ -170,10 +161,10 @@ public class CipherBlockChainingSubstitutions {
|
||||
|
||||
private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt, boolean withOriginalKey) {
|
||||
AESCryptSubstitutions.checkArgs(in, inOffset, out, outOffset);
|
||||
Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
|
||||
Object aesCipher = getAESCryptClass().cast(embeddedCipher);
|
||||
Object kObject = RawLoadNode.load(aesCipher, AESCryptSubstitutions.kOffset, JavaKind.Object, LocationIdentity.any());
|
||||
Object rObject = RawLoadNode.load(realReceiver, rOffset, JavaKind.Object, LocationIdentity.any());
|
||||
Object realReceiver = piCastNonNull(rcvr, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT));
|
||||
Object aesCipher = piCastNonNull(embeddedCipher, aesCryptType(INJECTED_INTRINSIC_CONTEXT));
|
||||
Object kObject = RawLoadNode.load(aesCipher, AESCryptSubstitutions.kOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
|
||||
Object rObject = RawLoadNode.load(realReceiver, rOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
|
||||
Pointer kAddr = Word.objectToTrackedPointer(kObject).add(ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Int));
|
||||
Pointer rAddr = Word.objectToTrackedPointer(rObject).add(ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte));
|
||||
Word inAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(in, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte) + inOffset));
|
||||
@ -182,7 +173,7 @@ public class CipherBlockChainingSubstitutions {
|
||||
encryptAESCryptStub(ENCRYPT, inAddr, outAddr, kAddr, rAddr, inLength);
|
||||
} else {
|
||||
if (withOriginalKey) {
|
||||
Object lastKeyObject = RawLoadNode.load(aesCipher, AESCryptSubstitutions.lastKeyOffset, JavaKind.Object, LocationIdentity.any());
|
||||
Object lastKeyObject = RawLoadNode.load(aesCipher, AESCryptSubstitutions.lastKeyOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
|
||||
Pointer lastKeyAddr = Word.objectToTrackedPointer(lastKeyObject).add(ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte));
|
||||
decryptAESCryptWithOriginalKeyStub(DECRYPT_WITH_ORIGINAL_KEY, inAddr, outAddr, kAddr, rAddr, inLength, lastKeyAddr);
|
||||
} else {
|
||||
|
@ -27,7 +27,8 @@ package org.graalvm.compiler.hotspot.replacements;
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_VMCONFIG;
|
||||
import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.VERIFY_OOP;
|
||||
import static org.graalvm.compiler.hotspot.replacements.UnsafeAccess.UNSAFE;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.Fold;
|
||||
import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
|
||||
@ -40,10 +41,10 @@ import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
|
||||
import org.graalvm.compiler.graph.Node.NodeIntrinsic;
|
||||
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.nodes.ComputeObjectAddressNode;
|
||||
import org.graalvm.compiler.hotspot.word.KlassPointer;
|
||||
import org.graalvm.compiler.nodes.CanonicalizableLocation;
|
||||
import org.graalvm.compiler.nodes.CompressionNode;
|
||||
import org.graalvm.compiler.nodes.ComputeObjectAddressNode;
|
||||
import org.graalvm.compiler.nodes.ConstantNode;
|
||||
import org.graalvm.compiler.nodes.NamedLocationIdentity;
|
||||
import org.graalvm.compiler.nodes.NodeView;
|
||||
@ -52,6 +53,7 @@ import org.graalvm.compiler.nodes.extended.ForeignCallNode;
|
||||
import org.graalvm.compiler.nodes.extended.LoadHubNode;
|
||||
import org.graalvm.compiler.nodes.extended.RawLoadNode;
|
||||
import org.graalvm.compiler.nodes.extended.StoreHubNode;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
|
||||
import org.graalvm.compiler.nodes.memory.Access;
|
||||
import org.graalvm.compiler.nodes.memory.address.AddressNode;
|
||||
import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
|
||||
@ -70,7 +72,10 @@ import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
|
||||
import jdk.vm.ci.meta.Assumptions;
|
||||
import jdk.vm.ci.meta.Assumptions.AssumptionResult;
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
import jdk.vm.ci.meta.ResolvedJavaField;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
import jdk.vm.ci.meta.UnresolvedJavaType;
|
||||
|
||||
//JaCoCo Exclude
|
||||
|
||||
@ -133,6 +138,28 @@ public class HotSpotReplacementsUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static ResolvedJavaType methodHolderClass(@Fold.InjectedParameter IntrinsicContext context) {
|
||||
return context.getOriginalMethod().getDeclaringClass();
|
||||
}
|
||||
|
||||
static ResolvedJavaType getType(@Fold.InjectedParameter IntrinsicContext context, String typeName) {
|
||||
try {
|
||||
UnresolvedJavaType unresolved = UnresolvedJavaType.create(typeName);
|
||||
return unresolved.resolve(methodHolderClass(context));
|
||||
} catch (LinkageError e) {
|
||||
throw new GraalError(e);
|
||||
}
|
||||
}
|
||||
|
||||
static int getFieldOffset(ResolvedJavaType type, String fieldName) {
|
||||
for (ResolvedJavaField field : type.getInstanceFields(true)) {
|
||||
if (field.getName().equals(fieldName)) {
|
||||
return field.getOffset();
|
||||
}
|
||||
}
|
||||
throw new GraalError("missing field " + fieldName);
|
||||
}
|
||||
|
||||
public static HotSpotJVMCIRuntime runtime() {
|
||||
return HotSpotJVMCIRuntime.runtime();
|
||||
}
|
||||
@ -143,9 +170,8 @@ public class HotSpotReplacementsUtil {
|
||||
}
|
||||
|
||||
@Fold
|
||||
public static GraalHotSpotVMConfig config(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
assert config != null;
|
||||
return config;
|
||||
public static int klassLayoutHelperNeutralValue(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.klassLayoutHelperNeutralValue;
|
||||
}
|
||||
|
||||
@Fold
|
||||
@ -199,13 +225,6 @@ public class HotSpotReplacementsUtil {
|
||||
return config.pendingExceptionOffset;
|
||||
}
|
||||
|
||||
public static final LocationIdentity OBJECT_RESULT_LOCATION = NamedLocationIdentity.mutable("ObjectResult");
|
||||
|
||||
@Fold
|
||||
static int objectResultOffset(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.threadObjectResultOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see GraalHotSpotVMConfig#threadExceptionOopOffset
|
||||
*/
|
||||
@ -262,17 +281,6 @@ public class HotSpotReplacementsUtil {
|
||||
return thread.readObject(threadPendingExceptionOffset(INJECTED_VMCONFIG), PENDING_EXCEPTION_LOCATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets and clears the object result from a runtime call stored in a thread local.
|
||||
*
|
||||
* @return the object that was in the thread local
|
||||
*/
|
||||
public static Object getAndClearObjectResult(Word thread) {
|
||||
Object result = thread.readObject(objectResultOffset(INJECTED_VMCONFIG), OBJECT_RESULT_LOCATION);
|
||||
thread.writeObject(objectResultOffset(INJECTED_VMCONFIG), null, OBJECT_RESULT_LOCATION);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* As far as Java code is concerned this can be considered immutable: it is set just after the
|
||||
* JavaThread is created, before it is published. After that, it is never changed.
|
||||
@ -307,8 +315,8 @@ public class HotSpotReplacementsUtil {
|
||||
}
|
||||
|
||||
@Fold
|
||||
public static int pageSize() {
|
||||
return UNSAFE.pageSize();
|
||||
public static int pageSize(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.vmPageSize;
|
||||
}
|
||||
|
||||
public static final LocationIdentity PROTOTYPE_MARK_WORD_LOCATION = NamedLocationIdentity.mutable("PrototypeMarkWord");
|
||||
@ -348,6 +356,56 @@ public class HotSpotReplacementsUtil {
|
||||
}
|
||||
};
|
||||
|
||||
@Fold
|
||||
public static int allocatePrefetchStyle(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.allocatePrefetchStyle;
|
||||
}
|
||||
|
||||
@Fold
|
||||
public static int allocatePrefetchLines(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.allocatePrefetchLines;
|
||||
}
|
||||
|
||||
@Fold
|
||||
public static int allocatePrefetchDistance(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.allocatePrefetchDistance;
|
||||
}
|
||||
|
||||
@Fold
|
||||
public static int allocateInstancePrefetchLines(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.allocateInstancePrefetchLines;
|
||||
}
|
||||
|
||||
@Fold
|
||||
public static int allocatePrefetchStepSize(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.allocatePrefetchStepSize;
|
||||
}
|
||||
|
||||
@Fold
|
||||
public static int invocationCounterIncrement(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.invocationCounterIncrement;
|
||||
}
|
||||
|
||||
@Fold
|
||||
public static int invocationCounterOffset(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.invocationCounterOffset;
|
||||
}
|
||||
|
||||
@Fold
|
||||
public static int backedgeCounterOffset(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.backedgeCounterOffset;
|
||||
}
|
||||
|
||||
@Fold
|
||||
public static int invocationCounterShift(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.invocationCounterShift;
|
||||
}
|
||||
|
||||
@Fold
|
||||
public static int stackBias(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.stackBias;
|
||||
}
|
||||
|
||||
@NodeIntrinsic(value = KlassLayoutHelperNode.class)
|
||||
public static native int readLayoutHelper(KlassPointer object);
|
||||
|
||||
@ -365,7 +423,7 @@ public class HotSpotReplacementsUtil {
|
||||
* sure these are still ints and haven't changed.
|
||||
*/
|
||||
final int layoutHelper = readLayoutHelper(klassNonNull);
|
||||
final int layoutHelperNeutralValue = config(INJECTED_VMCONFIG).klassLayoutHelperNeutralValue;
|
||||
final int layoutHelperNeutralValue = klassLayoutHelperNeutralValue(INJECTED_VMCONFIG);
|
||||
return (layoutHelper < layoutHelperNeutralValue);
|
||||
}
|
||||
|
||||
@ -518,16 +576,16 @@ public class HotSpotReplacementsUtil {
|
||||
* Idiom for making {@link GraalHotSpotVMConfig} a constant.
|
||||
*/
|
||||
@Fold
|
||||
public static GraalHotSpotVMConfig getConfig(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config;
|
||||
public static int objectAlignment(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.objectAlignment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls {@link #arrayAllocationSize(int, int, int, GraalHotSpotVMConfig)} using an injected VM
|
||||
* configuration object.
|
||||
* Calls {@link #arrayAllocationSize(int, int, int, int)} using an injected VM configuration
|
||||
* object.
|
||||
*/
|
||||
public static int arrayAllocationSize(int length, int headerSize, int log2ElementSize) {
|
||||
return arrayAllocationSize(length, headerSize, log2ElementSize, getConfig(INJECTED_VMCONFIG));
|
||||
return arrayAllocationSize(length, headerSize, log2ElementSize, objectAlignment(INJECTED_VMCONFIG));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -538,12 +596,11 @@ public class HotSpotReplacementsUtil {
|
||||
* @param length the number of elements in the array
|
||||
* @param headerSize the size of the array header
|
||||
* @param log2ElementSize log2 of the size of an element in the array
|
||||
* @param config the VM configuration providing the
|
||||
* {@linkplain GraalHotSpotVMConfig#objectAlignment object alignment requirement}
|
||||
* @param alignment the {@linkplain GraalHotSpotVMConfig#objectAlignment object alignment
|
||||
* requirement}
|
||||
* @return the size of the memory chunk
|
||||
*/
|
||||
public static int arrayAllocationSize(int length, int headerSize, int log2ElementSize, GraalHotSpotVMConfig config) {
|
||||
int alignment = config.objectAlignment;
|
||||
public static int arrayAllocationSize(int length, int headerSize, int log2ElementSize, int alignment) {
|
||||
int size = (length << log2ElementSize) + headerSize + (alignment - 1);
|
||||
int mask = ~(alignment - 1);
|
||||
return size & mask;
|
||||
@ -786,12 +843,8 @@ public class HotSpotReplacementsUtil {
|
||||
}
|
||||
|
||||
@Fold
|
||||
public static long referentOffset() {
|
||||
try {
|
||||
return UNSAFE.objectFieldOffset(java.lang.ref.Reference.class.getDeclaredField("referent"));
|
||||
} catch (Exception e) {
|
||||
throw new GraalError(e);
|
||||
}
|
||||
public static long referentOffset(@InjectedParameter MetaAccessProvider metaAccessProvider) {
|
||||
return getFieldOffset(metaAccessProvider.lookupJavaType(Reference.class), "referent");
|
||||
}
|
||||
|
||||
public static final LocationIdentity OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("ObjArrayKlass::_element_klass") {
|
||||
|
@ -26,7 +26,9 @@ package org.graalvm.compiler.hotspot.replacements;
|
||||
|
||||
import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE;
|
||||
import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE;
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_OPTIONVALUES;
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
|
||||
import static org.graalvm.compiler.hotspot.nodes.AcquiredCASLockNode.mark;
|
||||
import static org.graalvm.compiler.hotspot.nodes.BeginLockScopeNode.beginLockScope;
|
||||
import static org.graalvm.compiler.hotspot.nodes.EndLockScopeNode.endLockScope;
|
||||
import static org.graalvm.compiler.hotspot.nodes.VMErrorNode.vmError;
|
||||
@ -40,7 +42,6 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.ageMaskInPlace;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.biasedLockMaskInPlace;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.biasedLockPattern;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.config;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.epochMaskInPlace;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadWordFromObject;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.lockDisplacedMarkOffset;
|
||||
@ -53,6 +54,7 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.pageSize;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.prototypeMarkWordOffset;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.stackBias;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.unlockedMask;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.useBiasedLocking;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.verifyOop;
|
||||
@ -69,7 +71,10 @@ import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_LIKE
|
||||
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY;
|
||||
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.VERY_FAST_PATH_PROBABILITY;
|
||||
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
|
||||
import static org.graalvm.compiler.nodes.extended.MembarNode.memoryBarrier;
|
||||
import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
|
||||
import static jdk.internal.vm.compiler.word.WordFactory.unsigned;
|
||||
import static jdk.internal.vm.compiler.word.WordFactory.zero;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -89,7 +94,6 @@ import org.graalvm.compiler.graph.iterators.NodeIterable;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
|
||||
import org.graalvm.compiler.hotspot.nodes.AcquiredCASLockNode;
|
||||
import org.graalvm.compiler.hotspot.nodes.CurrentLockNode;
|
||||
import org.graalvm.compiler.hotspot.nodes.FastAcquireBiasedLockNode;
|
||||
import org.graalvm.compiler.hotspot.nodes.MonitorCounterNode;
|
||||
@ -219,13 +223,13 @@ public class MonitorSnippets implements Snippets {
|
||||
private static final boolean PROFILE_CONTEXT = false;
|
||||
|
||||
@Fold
|
||||
static boolean doProfile(OptionValues options) {
|
||||
static boolean doProfile(@Fold.InjectedParameter OptionValues options) {
|
||||
return ProfileMonitors.getValue(options);
|
||||
}
|
||||
|
||||
@Snippet
|
||||
public static void monitorenter(Object object, KlassPointer hub, @ConstantParameter int lockDepth, @ConstantParameter Register threadRegister, @ConstantParameter Register stackPointerRegister,
|
||||
@ConstantParameter boolean trace, @ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
|
||||
@ConstantParameter boolean trace, @ConstantParameter Counters counters) {
|
||||
verifyOop(object);
|
||||
|
||||
// Load the mark word - this includes a null-check on object
|
||||
@ -238,17 +242,17 @@ public class MonitorSnippets implements Snippets {
|
||||
trace(trace, " lock: 0x%016lx\n", lock);
|
||||
trace(trace, " mark: 0x%016lx\n", mark);
|
||||
|
||||
incCounter(options);
|
||||
incCounter();
|
||||
|
||||
if (useBiasedLocking(INJECTED_VMCONFIG)) {
|
||||
if (tryEnterBiased(object, hub, lock, mark, threadRegister, trace, options, counters)) {
|
||||
if (tryEnterBiased(object, hub, lock, mark, threadRegister, trace, counters)) {
|
||||
return;
|
||||
}
|
||||
// not biased, fall-through
|
||||
}
|
||||
if (inlineFastLockSupported(options) && probability(SLOW_PATH_PROBABILITY, mark.and(monitorMask(INJECTED_VMCONFIG)).notEqual(0))) {
|
||||
if (inlineFastLockSupported() && probability(SLOW_PATH_PROBABILITY, mark.and(monitorMask(INJECTED_VMCONFIG)).notEqual(0))) {
|
||||
// Inflated case
|
||||
if (tryEnterInflated(object, lock, mark, threadRegister, trace, options, counters)) {
|
||||
if (tryEnterInflated(object, lock, mark, threadRegister, trace, counters)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@ -266,9 +270,9 @@ public class MonitorSnippets implements Snippets {
|
||||
// (address of) the lock slot into the object's mark word.
|
||||
Word currentMark = objectPointer.compareAndSwapWord(markOffset(INJECTED_VMCONFIG), unlockedMark, lock, MARK_WORD_LOCATION);
|
||||
if (probability(FAST_PATH_PROBABILITY, currentMark.equal(unlockedMark))) {
|
||||
traceObject(trace, "+lock{cas}", object, true, options);
|
||||
traceObject(trace, "+lock{cas}", object, true);
|
||||
counters.lockCas.inc();
|
||||
AcquiredCASLockNode.mark(object);
|
||||
mark(object);
|
||||
return;
|
||||
} else {
|
||||
trace(trace, " currentMark: 0x%016lx\n", currentMark);
|
||||
@ -287,16 +291,16 @@ public class MonitorSnippets implements Snippets {
|
||||
//
|
||||
// assuming both the stack pointer and page_size have their least
|
||||
// significant 2 bits cleared and page_size is a power of 2
|
||||
final Word alignedMask = WordFactory.unsigned(wordSize() - 1);
|
||||
final Word stackPointer = registerAsWord(stackPointerRegister).add(config(INJECTED_VMCONFIG).stackBias);
|
||||
if (probability(FAST_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).equal(0))) {
|
||||
final Word alignedMask = unsigned(wordSize() - 1);
|
||||
final Word stackPointer = registerAsWord(stackPointerRegister).add(stackBias(INJECTED_VMCONFIG));
|
||||
if (probability(FAST_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize(INJECTED_VMCONFIG))).equal(0))) {
|
||||
// Recursively locked => write 0 to the lock slot
|
||||
lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), WordFactory.zero(), DISPLACED_MARK_WORD_LOCATION);
|
||||
traceObject(trace, "+lock{cas:recursive}", object, true, options);
|
||||
lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), zero(), DISPLACED_MARK_WORD_LOCATION);
|
||||
traceObject(trace, "+lock{cas:recursive}", object, true);
|
||||
counters.lockCasRecursive.inc();
|
||||
return;
|
||||
}
|
||||
traceObject(trace, "+lock{stub:failed-cas/stack}", object, true, options);
|
||||
traceObject(trace, "+lock{stub:failed-cas/stack}", object, true);
|
||||
counters.lockStubFailedCas.inc();
|
||||
}
|
||||
}
|
||||
@ -304,7 +308,7 @@ public class MonitorSnippets implements Snippets {
|
||||
monitorenterStubC(MONITORENTER, object, lock);
|
||||
}
|
||||
|
||||
private static boolean tryEnterBiased(Object object, KlassPointer hub, Word lock, Word mark, Register threadRegister, boolean trace, OptionValues options, Counters counters) {
|
||||
private static boolean tryEnterBiased(Object object, KlassPointer hub, Word lock, Word mark, Register threadRegister, boolean trace, Counters counters) {
|
||||
// See whether the lock is currently biased toward our thread and
|
||||
// whether the epoch is still valid.
|
||||
// Note that the runtime guarantees sufficient alignment of JavaThread
|
||||
@ -321,7 +325,7 @@ public class MonitorSnippets implements Snippets {
|
||||
trace(trace, " tmp: 0x%016lx\n", tmp);
|
||||
if (probability(FAST_PATH_PROBABILITY, tmp.equal(0))) {
|
||||
// Object is already biased to current thread -> done
|
||||
traceObject(trace, "+lock{bias:existing}", object, true, options);
|
||||
traceObject(trace, "+lock{bias:existing}", object, true);
|
||||
counters.lockBiasExisting.inc();
|
||||
FastAcquireBiasedLockNode.mark(object);
|
||||
return true;
|
||||
@ -362,14 +366,14 @@ public class MonitorSnippets implements Snippets {
|
||||
trace(trace, " biasedMark: 0x%016lx\n", biasedMark);
|
||||
if (probability(VERY_FAST_PATH_PROBABILITY, objectPointer.logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG), unbiasedMark, biasedMark, MARK_WORD_LOCATION))) {
|
||||
// Object is now biased to current thread -> done
|
||||
traceObject(trace, "+lock{bias:acquired}", object, true, options);
|
||||
traceObject(trace, "+lock{bias:acquired}", object, true);
|
||||
counters.lockBiasAcquired.inc();
|
||||
return true;
|
||||
}
|
||||
// If the biasing toward our thread failed, this means that another thread
|
||||
// owns the bias and we need to revoke that bias. The revocation will occur
|
||||
// in the interpreter runtime.
|
||||
traceObject(trace, "+lock{stub:revoke}", object, true, options);
|
||||
traceObject(trace, "+lock{stub:revoke}", object, true);
|
||||
counters.lockStubRevoke.inc();
|
||||
} else {
|
||||
// At this point we know the epoch has expired, meaning that the
|
||||
@ -382,14 +386,14 @@ public class MonitorSnippets implements Snippets {
|
||||
trace(trace, " biasedMark: 0x%016lx\n", biasedMark);
|
||||
if (probability(VERY_FAST_PATH_PROBABILITY, objectPointer.logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG), mark, biasedMark, MARK_WORD_LOCATION))) {
|
||||
// Object is now biased to current thread -> done
|
||||
traceObject(trace, "+lock{bias:transfer}", object, true, options);
|
||||
traceObject(trace, "+lock{bias:transfer}", object, true);
|
||||
counters.lockBiasTransfer.inc();
|
||||
return true;
|
||||
}
|
||||
// If the biasing toward our thread failed, then another thread
|
||||
// succeeded in biasing it toward itself and we need to revoke that
|
||||
// bias. The revocation will occur in the runtime in the slow case.
|
||||
traceObject(trace, "+lock{stub:epoch-expired}", object, true, options);
|
||||
traceObject(trace, "+lock{stub:epoch-expired}", object, true);
|
||||
counters.lockStubEpochExpired.inc();
|
||||
}
|
||||
// slow-path runtime-call
|
||||
@ -424,19 +428,19 @@ public class MonitorSnippets implements Snippets {
|
||||
}
|
||||
|
||||
@Fold
|
||||
public static boolean useFastInflatedLocking(OptionValues options) {
|
||||
public static boolean useFastInflatedLocking(@Fold.InjectedParameter OptionValues options) {
|
||||
return SimpleFastInflatedLocking.getValue(options);
|
||||
}
|
||||
|
||||
private static boolean inlineFastLockSupported(OptionValues options) {
|
||||
return inlineFastLockSupported(INJECTED_VMCONFIG, options);
|
||||
private static boolean inlineFastLockSupported() {
|
||||
return inlineFastLockSupported(INJECTED_VMCONFIG, INJECTED_OPTIONVALUES);
|
||||
}
|
||||
|
||||
private static boolean inlineFastLockSupported(GraalHotSpotVMConfig config, OptionValues options) {
|
||||
return useFastInflatedLocking(options) && monitorMask(config) >= 0 && objectMonitorOwnerOffset(config) >= 0;
|
||||
}
|
||||
|
||||
private static boolean tryEnterInflated(Object object, Word lock, Word mark, Register threadRegister, boolean trace, OptionValues options, Counters counters) {
|
||||
private static boolean tryEnterInflated(Object object, Word lock, Word mark, Register threadRegister, boolean trace, Counters counters) {
|
||||
// write non-zero value to lock slot
|
||||
lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), lock, DISPLACED_MARK_WORD_LOCATION);
|
||||
// mark is a pointer to the ObjectMonitor + monitorMask
|
||||
@ -447,15 +451,15 @@ public class MonitorSnippets implements Snippets {
|
||||
// it appears unlocked (owner == 0)
|
||||
if (probability(FREQUENT_PROBABILITY, monitor.logicCompareAndSwapWord(ownerOffset, owner, registerAsWord(threadRegister), OBJECT_MONITOR_OWNER_LOCATION))) {
|
||||
// success
|
||||
traceObject(trace, "+lock{inflated:cas}", object, true, options);
|
||||
traceObject(trace, "+lock{inflated:cas}", object, true);
|
||||
counters.inflatedCas.inc();
|
||||
return true;
|
||||
} else {
|
||||
traceObject(trace, "+lock{stub:inflated:failed-cas}", object, true, options);
|
||||
traceObject(trace, "+lock{stub:inflated:failed-cas}", object, true);
|
||||
counters.inflatedFailedCas.inc();
|
||||
}
|
||||
} else {
|
||||
traceObject(trace, "+lock{stub:inflated:owned}", object, true, options);
|
||||
traceObject(trace, "+lock{stub:inflated:owned}", object, true);
|
||||
counters.inflatedOwned.inc();
|
||||
}
|
||||
return false;
|
||||
@ -465,22 +469,22 @@ public class MonitorSnippets implements Snippets {
|
||||
* Calls straight out to the monitorenter stub.
|
||||
*/
|
||||
@Snippet
|
||||
public static void monitorenterStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace, @ConstantParameter OptionValues options) {
|
||||
public static void monitorenterStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace) {
|
||||
verifyOop(object);
|
||||
incCounter(options);
|
||||
incCounter();
|
||||
if (object == null) {
|
||||
DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException);
|
||||
}
|
||||
// BeginLockScope nodes do not read from object so a use of object
|
||||
// cannot float about the null check above
|
||||
final Word lock = beginLockScope(lockDepth);
|
||||
traceObject(trace, "+lock{stub}", object, true, options);
|
||||
traceObject(trace, "+lock{stub}", object, true);
|
||||
monitorenterStubC(MONITORENTER, object, lock);
|
||||
}
|
||||
|
||||
@Snippet
|
||||
public static void monitorexit(Object object, @ConstantParameter int lockDepth, @ConstantParameter Register threadRegister, @ConstantParameter boolean trace,
|
||||
@ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
|
||||
@ConstantParameter Counters counters) {
|
||||
trace(trace, " object: 0x%016lx\n", Word.objectToTrackedPointer(object));
|
||||
final Word mark = loadWordFromObject(object, markOffset(INJECTED_VMCONFIG));
|
||||
if (useBiasedLocking(INJECTED_VMCONFIG)) {
|
||||
@ -493,8 +497,8 @@ public class MonitorSnippets implements Snippets {
|
||||
trace(trace, " mark: 0x%016lx\n", mark);
|
||||
if (probability(FREQUENT_PROBABILITY, mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)).equal(WordFactory.unsigned(biasedLockPattern(INJECTED_VMCONFIG))))) {
|
||||
endLockScope();
|
||||
decCounter(options);
|
||||
traceObject(trace, "-lock{bias}", object, false, options);
|
||||
decCounter();
|
||||
traceObject(trace, "-lock{bias}", object, false);
|
||||
counters.unlockBias.inc();
|
||||
return;
|
||||
}
|
||||
@ -508,10 +512,10 @@ public class MonitorSnippets implements Snippets {
|
||||
|
||||
if (probability(NOT_LIKELY_PROBABILITY, displacedMark.equal(0))) {
|
||||
// Recursive locking => done
|
||||
traceObject(trace, "-lock{recursive}", object, false, options);
|
||||
traceObject(trace, "-lock{recursive}", object, false);
|
||||
counters.unlockCasRecursive.inc();
|
||||
} else {
|
||||
if (!tryExitInflated(object, mark, lock, threadRegister, trace, options, counters)) {
|
||||
if (!tryExitInflated(object, mark, lock, threadRegister, trace, counters)) {
|
||||
verifyOop(object);
|
||||
// Test if object's mark word is pointing to the displaced mark word, and if so,
|
||||
// restore
|
||||
@ -519,18 +523,18 @@ public class MonitorSnippets implements Snippets {
|
||||
// the displaced mark word, do unlocking via runtime call.
|
||||
Pointer objectPointer = Word.objectToTrackedPointer(object);
|
||||
if (probability(VERY_FAST_PATH_PROBABILITY, objectPointer.logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG), lock, displacedMark, MARK_WORD_LOCATION))) {
|
||||
traceObject(trace, "-lock{cas}", object, false, options);
|
||||
traceObject(trace, "-lock{cas}", object, false);
|
||||
counters.unlockCas.inc();
|
||||
} else {
|
||||
// The object's mark word was not pointing to the displaced header
|
||||
traceObject(trace, "-lock{stub}", object, false, options);
|
||||
traceObject(trace, "-lock{stub}", object, false);
|
||||
counters.unlockStub.inc();
|
||||
monitorexitStubC(MONITOREXIT, object, lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
endLockScope();
|
||||
decCounter(options);
|
||||
decCounter();
|
||||
}
|
||||
|
||||
private static boolean inlineFastUnlockSupported(OptionValues options) {
|
||||
@ -542,8 +546,8 @@ public class MonitorSnippets implements Snippets {
|
||||
objectMonitorOwnerOffset(config) >= 0 && objectMonitorRecursionsOffset(config) >= 0;
|
||||
}
|
||||
|
||||
private static boolean tryExitInflated(Object object, Word mark, Word lock, Register threadRegister, boolean trace, OptionValues options, Counters counters) {
|
||||
if (!inlineFastUnlockSupported(options)) {
|
||||
private static boolean tryExitInflated(Object object, Word mark, Word lock, Register threadRegister, boolean trace, Counters counters) {
|
||||
if (!inlineFastUnlockSupported(INJECTED_OPTIONVALUES)) {
|
||||
return false;
|
||||
}
|
||||
if (probability(SLOW_PATH_PROBABILITY, mark.and(monitorMask(INJECTED_VMCONFIG)).notEqual(0))) {
|
||||
@ -565,15 +569,15 @@ public class MonitorSnippets implements Snippets {
|
||||
// cxq == 0 && entryList == 0
|
||||
// Nobody is waiting, success
|
||||
// release_store
|
||||
MembarNode.memoryBarrier(LOAD_STORE | STORE_STORE);
|
||||
monitor.writeWord(ownerOffset, WordFactory.zero());
|
||||
traceObject(trace, "-lock{inflated:simple}", object, false, options);
|
||||
memoryBarrier(LOAD_STORE | STORE_STORE);
|
||||
monitor.writeWord(ownerOffset, zero());
|
||||
traceObject(trace, "-lock{inflated:simple}", object, false);
|
||||
counters.unlockInflatedSimple.inc();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
counters.unlockStubInflated.inc();
|
||||
traceObject(trace, "-lock{stub:inflated}", object, false, options);
|
||||
traceObject(trace, "-lock{stub:inflated}", object, false);
|
||||
monitorexitStubC(MONITOREXIT, object, lock);
|
||||
return true;
|
||||
}
|
||||
@ -584,17 +588,17 @@ public class MonitorSnippets implements Snippets {
|
||||
* Calls straight out to the monitorexit stub.
|
||||
*/
|
||||
@Snippet
|
||||
public static void monitorexitStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace, @ConstantParameter OptionValues options) {
|
||||
public static void monitorexitStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace) {
|
||||
verifyOop(object);
|
||||
traceObject(trace, "-lock{stub}", object, false, options);
|
||||
traceObject(trace, "-lock{stub}", object, false);
|
||||
final Word lock = CurrentLockNode.currentLock(lockDepth);
|
||||
monitorexitStubC(MONITOREXIT, object, lock);
|
||||
endLockScope();
|
||||
decCounter(options);
|
||||
decCounter();
|
||||
}
|
||||
|
||||
public static void traceObject(boolean enabled, String action, Object object, boolean enter, OptionValues options) {
|
||||
if (doProfile(options)) {
|
||||
public static void traceObject(boolean enabled, String action, Object object, boolean enter) {
|
||||
if (doProfile(INJECTED_OPTIONVALUES)) {
|
||||
DynamicCounterNode.counter(enter ? "number of monitor enters" : "number of monitor exits", action, 1, PROFILE_CONTEXT);
|
||||
}
|
||||
if (enabled) {
|
||||
@ -622,20 +626,20 @@ public class MonitorSnippets implements Snippets {
|
||||
static native void bkpt(Object object, Word mark, Word tmp, Word value);
|
||||
|
||||
@Fold
|
||||
static boolean verifyBalancedMonitors(OptionValues options) {
|
||||
static boolean verifyBalancedMonitors(@Fold.InjectedParameter OptionValues options) {
|
||||
return VerifyBalancedMonitors.getValue(options);
|
||||
}
|
||||
|
||||
public static void incCounter(OptionValues options) {
|
||||
if (verifyBalancedMonitors(options)) {
|
||||
static void incCounter() {
|
||||
if (verifyBalancedMonitors(INJECTED_OPTIONVALUES)) {
|
||||
final Word counter = MonitorCounterNode.counter();
|
||||
final int count = counter.readInt(0, MONITOR_COUNTER_LOCATION);
|
||||
counter.writeInt(0, count + 1, MONITOR_COUNTER_LOCATION);
|
||||
}
|
||||
}
|
||||
|
||||
public static void decCounter(OptionValues options) {
|
||||
if (verifyBalancedMonitors(options)) {
|
||||
public static void decCounter() {
|
||||
if (verifyBalancedMonitors(INJECTED_OPTIONVALUES)) {
|
||||
final Word counter = MonitorCounterNode.counter();
|
||||
final int count = counter.readInt(0, MONITOR_COUNTER_LOCATION);
|
||||
counter.writeInt(0, count - 1, MONITOR_COUNTER_LOCATION);
|
||||
@ -750,14 +754,12 @@ public class MonitorSnippets implements Snippets {
|
||||
args.addConst("threadRegister", registers.getThreadRegister());
|
||||
args.addConst("stackPointerRegister", registers.getStackPointerRegister());
|
||||
args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(graph));
|
||||
args.addConst("options", graph.getOptions());
|
||||
args.addConst("counters", counters);
|
||||
} else {
|
||||
args = new Arguments(monitorenterStub, graph.getGuardsStage(), tool.getLoweringStage());
|
||||
args.add("object", monitorenterNode.object());
|
||||
args.addConst("lockDepth", monitorenterNode.getMonitorId().getLockDepth());
|
||||
args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(graph));
|
||||
args.addConst("options", graph.getOptions());
|
||||
args.addConst("counters", counters);
|
||||
}
|
||||
|
||||
@ -777,7 +779,6 @@ public class MonitorSnippets implements Snippets {
|
||||
args.addConst("lockDepth", monitorexitNode.getMonitorId().getLockDepth());
|
||||
args.addConst("threadRegister", registers.getThreadRegister());
|
||||
args.addConst("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(graph));
|
||||
args.addConst("options", graph.getOptions());
|
||||
args.addConst("counters", counters);
|
||||
|
||||
template(monitorexitNode, args).instantiate(providers.getMetaAccess(), monitorexitNode, DEFAULT_REPLACER, args);
|
||||
|
@ -28,6 +28,7 @@ import static jdk.vm.ci.meta.DeoptimizationAction.None;
|
||||
import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
|
||||
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
|
||||
import static org.graalvm.compiler.core.common.calc.UnsignedMath.belowThan;
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_OPTIONVALUES;
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_VMCONFIG;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_ARRAY;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_ARRAY_OR_NULL;
|
||||
@ -41,10 +42,14 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PROTOTYPE_MARK_WORD_LOCATION;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_END_LOCATION;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_TOP_LOCATION;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.allocateInstancePrefetchLines;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.allocatePrefetchDistance;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.allocatePrefetchLines;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.allocatePrefetchStepSize;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.allocatePrefetchStyle;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayAllocationSize;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayKlassOffset;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayLengthOffset;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.config;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.initializeObjectHeader;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.instanceHeaderSize;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.isInstanceKlassFullyInitialized;
|
||||
@ -151,7 +156,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
}
|
||||
|
||||
@Fold
|
||||
static String createName(String path, String typeContext, OptionValues options) {
|
||||
static String createName(@Fold.InjectedParameter OptionValues options, String path, String typeContext) {
|
||||
switch (ProfileAllocationsContext.getValue(options)) {
|
||||
case AllocatingMethod:
|
||||
return "";
|
||||
@ -168,34 +173,33 @@ public class NewObjectSnippets implements Snippets {
|
||||
}
|
||||
|
||||
@Fold
|
||||
static boolean doProfile(OptionValues options) {
|
||||
static boolean doProfile(@Fold.InjectedParameter OptionValues options) {
|
||||
return ProfileAllocations.getValue(options);
|
||||
}
|
||||
|
||||
@Fold
|
||||
static boolean withContext(OptionValues options) {
|
||||
static boolean withContext(@Fold.InjectedParameter OptionValues options) {
|
||||
ProfileContext context = ProfileAllocationsContext.getValue(options);
|
||||
return context == ProfileContext.AllocatingMethod || context == ProfileContext.AllocatedTypesInMethod;
|
||||
}
|
||||
|
||||
protected static void profileAllocation(String path, long size, String typeContext, OptionValues options) {
|
||||
if (doProfile(options)) {
|
||||
String name = createName(path, typeContext, options);
|
||||
protected static void profileAllocation(String path, long size, String typeContext) {
|
||||
if (doProfile(INJECTED_OPTIONVALUES)) {
|
||||
String name = createName(INJECTED_OPTIONVALUES, path, typeContext);
|
||||
|
||||
boolean context = withContext(options);
|
||||
boolean context = withContext(INJECTED_OPTIONVALUES);
|
||||
DynamicCounterNode.counter("number of bytes allocated", name, size, context);
|
||||
DynamicCounterNode.counter("number of allocations", name, 1, context);
|
||||
}
|
||||
}
|
||||
|
||||
public static void emitPrefetchAllocate(Word address, boolean isArray) {
|
||||
GraalHotSpotVMConfig config = config(INJECTED_VMCONFIG);
|
||||
if (config.allocatePrefetchStyle > 0) {
|
||||
if (allocatePrefetchStyle(INJECTED_VMCONFIG) > 0) {
|
||||
// Insert a prefetch for each allocation only on the fast-path
|
||||
// Generate several prefetch instructions.
|
||||
int lines = isArray ? config.allocatePrefetchLines : config.allocateInstancePrefetchLines;
|
||||
int stepSize = config.allocatePrefetchStepSize;
|
||||
int distance = config.allocatePrefetchDistance;
|
||||
int lines = isArray ? allocatePrefetchLines(INJECTED_VMCONFIG) : allocateInstancePrefetchLines(INJECTED_VMCONFIG);
|
||||
int stepSize = allocatePrefetchStepSize(INJECTED_VMCONFIG);
|
||||
int distance = allocatePrefetchDistance(INJECTED_VMCONFIG);
|
||||
ExplodeLoopNode.explodeLoop();
|
||||
for (int i = 0; i < lines; i++) {
|
||||
PrefetchAllocateNode.prefetch(OffsetAddressNode.address(address, distance));
|
||||
@ -206,13 +210,13 @@ public class NewObjectSnippets implements Snippets {
|
||||
|
||||
@Snippet
|
||||
public static Object allocateInstance(@ConstantParameter int size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents,
|
||||
@ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext, @ConstantParameter OptionValues options,
|
||||
@ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext,
|
||||
@ConstantParameter Counters counters) {
|
||||
return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, hub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, options, counters));
|
||||
return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, hub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, counters));
|
||||
}
|
||||
|
||||
public static Object allocateInstanceHelper(int size, KlassPointer hub, Word prototypeMarkWord, boolean fillContents,
|
||||
Register threadRegister, boolean constantSize, String typeContext, OptionValues options, Counters counters) {
|
||||
Register threadRegister, boolean constantSize, String typeContext, Counters counters) {
|
||||
Object result;
|
||||
Word thread = registerAsWord(threadRegister);
|
||||
Word top = readTlabTop(thread);
|
||||
@ -223,12 +227,13 @@ public class NewObjectSnippets implements Snippets {
|
||||
emitPrefetchAllocate(newTop, false);
|
||||
result = formatObject(hub, size, top, prototypeMarkWord, fillContents, constantSize, counters);
|
||||
} else {
|
||||
if (counters != null && counters.stub != null) {
|
||||
counters.stub.inc();
|
||||
Counters theCounters = counters;
|
||||
if (theCounters != null && theCounters.stub != null) {
|
||||
theCounters.stub.inc();
|
||||
}
|
||||
result = newInstanceStub(hub);
|
||||
}
|
||||
profileAllocation("instance", size, typeContext, options);
|
||||
profileAllocation("instance", size, typeContext);
|
||||
return verifyOop(result);
|
||||
}
|
||||
|
||||
@ -248,18 +253,18 @@ public class NewObjectSnippets implements Snippets {
|
||||
|
||||
@Snippet
|
||||
public static Object allocateInstancePIC(@ConstantParameter int size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents,
|
||||
@ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext, @ConstantParameter OptionValues options,
|
||||
@ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext,
|
||||
@ConstantParameter Counters counters) {
|
||||
// Klass must be initialized by the time the first instance is allocated, therefore we can
|
||||
// just load it from the corresponding cell and avoid the resolution check. We have to use a
|
||||
// fixed load though, to prevent it from floating above the initialization.
|
||||
KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub);
|
||||
return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, picHub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, options, counters));
|
||||
return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, picHub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, counters));
|
||||
}
|
||||
|
||||
@Snippet
|
||||
public static Object allocateInstanceDynamic(Class<?> type, Class<?> classClass, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister,
|
||||
@ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
|
||||
@ConstantParameter Counters counters) {
|
||||
if (probability(SLOW_PATH_PROBABILITY, type == null)) {
|
||||
DeoptimizeNode.deopt(None, RuntimeConstraint);
|
||||
}
|
||||
@ -269,10 +274,10 @@ public class NewObjectSnippets implements Snippets {
|
||||
DeoptimizeNode.deopt(None, RuntimeConstraint);
|
||||
}
|
||||
|
||||
return PiNode.piCastToSnippetReplaceeStamp(allocateInstanceDynamicHelper(type, fillContents, threadRegister, options, counters, nonNullType));
|
||||
return PiNode.piCastToSnippetReplaceeStamp(allocateInstanceDynamicHelper(type, fillContents, threadRegister, counters, nonNullType));
|
||||
}
|
||||
|
||||
private static Object allocateInstanceDynamicHelper(Class<?> type, boolean fillContents, Register threadRegister, OptionValues options, Counters counters, Class<?> nonNullType) {
|
||||
private static Object allocateInstanceDynamicHelper(Class<?> type, boolean fillContents, Register threadRegister, Counters counters, Class<?> nonNullType) {
|
||||
KlassPointer hub = ClassGetHubNode.readClass(nonNullType);
|
||||
if (probability(FAST_PATH_PROBABILITY, !hub.isNull())) {
|
||||
KlassPointer nonNullHub = ClassGetHubNode.piCastNonNull(hub, SnippetAnchorNode.anchor());
|
||||
@ -291,7 +296,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
* FIXME(je,ds): we should actually pass typeContext instead of "" but late
|
||||
* binding of parameters is not yet supported by the GraphBuilderPlugin system.
|
||||
*/
|
||||
return allocateInstanceHelper(layoutHelper, nonNullHub, prototypeMarkWord, fillContents, threadRegister, false, "", options, counters);
|
||||
return allocateInstanceHelper(layoutHelper, nonNullHub, prototypeMarkWord, fillContents, threadRegister, false, "", counters);
|
||||
}
|
||||
} else {
|
||||
DeoptimizeNode.deopt(None, RuntimeConstraint);
|
||||
@ -308,19 +313,19 @@ public class NewObjectSnippets implements Snippets {
|
||||
@Snippet
|
||||
public static Object allocatePrimitiveArrayPIC(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize,
|
||||
@ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext,
|
||||
@ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
|
||||
@ConstantParameter Counters counters) {
|
||||
// Primitive array types are eagerly pre-resolved. We can use a floating load.
|
||||
KlassPointer picHub = LoadConstantIndirectlyNode.loadKlass(hub);
|
||||
return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters);
|
||||
return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, counters);
|
||||
}
|
||||
|
||||
@Snippet
|
||||
public static Object allocateArrayPIC(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize,
|
||||
@ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext,
|
||||
@ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
|
||||
@ConstantParameter Counters counters) {
|
||||
// Array type would be resolved by dominating resolution.
|
||||
KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub);
|
||||
return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters);
|
||||
return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, counters);
|
||||
}
|
||||
|
||||
@Snippet
|
||||
@ -333,9 +338,19 @@ public class NewObjectSnippets implements Snippets {
|
||||
@ConstantParameter Register threadRegister,
|
||||
@ConstantParameter boolean maybeUnroll,
|
||||
@ConstantParameter String typeContext,
|
||||
@ConstantParameter OptionValues options,
|
||||
@ConstantParameter Counters counters) {
|
||||
Object result = allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters);
|
||||
Object result = allocateArrayImpl(hub,
|
||||
length,
|
||||
prototypeMarkWord,
|
||||
headerSize,
|
||||
log2ElementSize,
|
||||
fillContents,
|
||||
threadRegister,
|
||||
maybeUnroll,
|
||||
typeContext,
|
||||
false,
|
||||
|
||||
counters);
|
||||
return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length);
|
||||
}
|
||||
|
||||
@ -349,7 +364,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
}
|
||||
|
||||
private static Object allocateArrayImpl(KlassPointer hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, Register threadRegister,
|
||||
boolean maybeUnroll, String typeContext, boolean skipNegativeCheck, OptionValues options, Counters counters) {
|
||||
boolean maybeUnroll, String typeContext, boolean skipNegativeCheck, Counters counters) {
|
||||
Object result;
|
||||
int allocationSize = arrayAllocationSize(length, headerSize, log2ElementSize);
|
||||
Word thread = registerAsWord(threadRegister);
|
||||
@ -360,14 +375,15 @@ public class NewObjectSnippets implements Snippets {
|
||||
probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) {
|
||||
writeTlabTop(thread, newTop);
|
||||
emitPrefetchAllocate(newTop, true);
|
||||
if (counters != null && counters.arrayLoopInit != null) {
|
||||
counters.arrayLoopInit.inc();
|
||||
Counters theCounters = counters;
|
||||
if (theCounters != null && theCounters.arrayLoopInit != null) {
|
||||
theCounters.arrayLoopInit.inc();
|
||||
}
|
||||
result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, counters);
|
||||
} else {
|
||||
result = newArrayStub(hub, length);
|
||||
}
|
||||
profileAllocation("array", allocationSize, typeContext, options);
|
||||
profileAllocation("array", allocationSize, typeContext);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -421,14 +437,14 @@ public class NewObjectSnippets implements Snippets {
|
||||
|
||||
@Snippet
|
||||
public static Object allocateArrayDynamic(Class<?> elementType, Class<?> voidClass, int length, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister,
|
||||
@ConstantParameter JavaKind knownElementKind, @ConstantParameter int knownLayoutHelper, Word prototypeMarkWord, @ConstantParameter OptionValues options,
|
||||
@ConstantParameter JavaKind knownElementKind, @ConstantParameter int knownLayoutHelper, Word prototypeMarkWord,
|
||||
@ConstantParameter Counters counters) {
|
||||
Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, threadRegister, knownElementKind, knownLayoutHelper, prototypeMarkWord, options, counters);
|
||||
Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, threadRegister, knownElementKind, knownLayoutHelper, prototypeMarkWord, counters);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Object allocateArrayDynamicImpl(Class<?> elementType, Class<?> voidClass, int length, boolean fillContents, Register threadRegister, JavaKind knownElementKind,
|
||||
int knownLayoutHelper, Word prototypeMarkWord, OptionValues options, Counters counters) {
|
||||
int knownLayoutHelper, Word prototypeMarkWord, Counters counters) {
|
||||
/*
|
||||
* We only need the dynamic check for void when we have no static information from
|
||||
* knownElementKind.
|
||||
@ -470,7 +486,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift(INJECTED_VMCONFIG)) & layoutHelperHeaderSizeMask(INJECTED_VMCONFIG);
|
||||
int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG);
|
||||
|
||||
Object result = allocateArrayImpl(nonNullKlass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, false, "dynamic type", true, options, counters);
|
||||
Object result = allocateArrayImpl(nonNullKlass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, false, "dynamic type", true, counters);
|
||||
return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length);
|
||||
}
|
||||
|
||||
@ -536,13 +552,14 @@ public class NewObjectSnippets implements Snippets {
|
||||
offset += 4;
|
||||
}
|
||||
ReplacementsUtil.runtimeAssert((offset & 0x7) == 0, "unaligned offset");
|
||||
Counters theCounters = counters;
|
||||
if (manualUnroll && ((size - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) {
|
||||
ReplacementsUtil.staticAssert(!constantSize, "size shouldn't be constant at instantiation time");
|
||||
// This case handles arrays of constant length. Instead of having a snippet variant for
|
||||
// each length, generate a chain of stores of maximum length. Once it's inlined the
|
||||
// break statement will trim excess stores.
|
||||
if (counters != null && counters.instanceSeqInit != null) {
|
||||
counters.instanceSeqInit.inc();
|
||||
if (theCounters != null && theCounters.instanceSeqInit != null) {
|
||||
theCounters.instanceSeqInit.inc();
|
||||
}
|
||||
|
||||
explodeLoop();
|
||||
@ -556,13 +573,13 @@ public class NewObjectSnippets implements Snippets {
|
||||
// Use Word instead of int to avoid extension to long in generated code
|
||||
Word off = WordFactory.signed(offset);
|
||||
if (constantSize && ((size - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) {
|
||||
if (counters != null && counters.instanceSeqInit != null) {
|
||||
counters.instanceSeqInit.inc();
|
||||
if (theCounters != null && theCounters.instanceSeqInit != null) {
|
||||
theCounters.instanceSeqInit.inc();
|
||||
}
|
||||
explodeLoop();
|
||||
} else {
|
||||
if (counters != null && counters.instanceLoopInit != null) {
|
||||
counters.instanceLoopInit.inc();
|
||||
if (theCounters != null && theCounters.instanceLoopInit != null) {
|
||||
theCounters.instanceLoopInit.inc();
|
||||
}
|
||||
}
|
||||
for (; off.rawValue() < size; off = off.add(8)) {
|
||||
@ -694,7 +711,6 @@ public class NewObjectSnippets implements Snippets {
|
||||
args.addConst("threadRegister", registers.getThreadRegister());
|
||||
args.addConst("constantSize", true);
|
||||
args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? type.toJavaName(false) : "");
|
||||
args.addConst("options", localOptions);
|
||||
args.addConst("counters", counters);
|
||||
|
||||
SnippetTemplate template = template(newInstanceNode, args);
|
||||
@ -738,7 +754,6 @@ public class NewObjectSnippets implements Snippets {
|
||||
args.addConst("threadRegister", registers.getThreadRegister());
|
||||
args.addConst("maybeUnroll", length.isConstant());
|
||||
args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? arrayType.toJavaName(false) : "");
|
||||
args.addConst("options", localOptions);
|
||||
args.addConst("counters", counters);
|
||||
SnippetTemplate template = template(newArrayNode, args);
|
||||
graph.getDebug().log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args);
|
||||
@ -747,14 +762,12 @@ public class NewObjectSnippets implements Snippets {
|
||||
|
||||
public void lower(DynamicNewInstanceNode newInstanceNode, HotSpotRegistersProvider registers, LoweringTool tool) {
|
||||
Arguments args = new Arguments(allocateInstanceDynamic, newInstanceNode.graph().getGuardsStage(), tool.getLoweringStage());
|
||||
OptionValues localOptions = newInstanceNode.getOptions();
|
||||
args.add("type", newInstanceNode.getInstanceType());
|
||||
ValueNode classClass = newInstanceNode.getClassClass();
|
||||
assert classClass != null;
|
||||
args.add("classClass", classClass);
|
||||
args.addConst("fillContents", newInstanceNode.fillContents());
|
||||
args.addConst("threadRegister", registers.getThreadRegister());
|
||||
args.addConst("options", localOptions);
|
||||
args.addConst("counters", counters);
|
||||
|
||||
SnippetTemplate template = template(newInstanceNode, args);
|
||||
@ -763,7 +776,6 @@ public class NewObjectSnippets implements Snippets {
|
||||
|
||||
public void lower(DynamicNewArrayNode newArrayNode, HotSpotRegistersProvider registers, LoweringTool tool) {
|
||||
StructuredGraph graph = newArrayNode.graph();
|
||||
OptionValues localOptions = graph.getOptions();
|
||||
Arguments args = new Arguments(allocateArrayDynamic, newArrayNode.graph().getGuardsStage(), tool.getLoweringStage());
|
||||
args.add("elementType", newArrayNode.getElementType());
|
||||
ValueNode voidClass = newArrayNode.getVoidClass();
|
||||
@ -784,7 +796,6 @@ public class NewObjectSnippets implements Snippets {
|
||||
args.addConst("knownLayoutHelper", 0);
|
||||
}
|
||||
args.add("prototypeMarkWord", lookupArrayClass(tool, JavaKind.Object).prototypeMarkWord());
|
||||
args.addConst("options", localOptions);
|
||||
args.addConst("counters", counters);
|
||||
SnippetTemplate template = template(newArrayNode, args);
|
||||
template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args);
|
||||
|
@ -24,13 +24,12 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.replacements;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
import org.graalvm.compiler.core.common.type.StampPair;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotLoweringProvider;
|
||||
import org.graalvm.compiler.nodeinfo.NodeInfo;
|
||||
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
|
||||
import org.graalvm.compiler.nodes.NodeView;
|
||||
@ -45,6 +44,7 @@ import org.graalvm.compiler.nodes.java.StoreFieldNode;
|
||||
import org.graalvm.compiler.nodes.spi.LoweringTool;
|
||||
import org.graalvm.compiler.nodes.spi.Replacements;
|
||||
import org.graalvm.compiler.nodes.type.StampTool;
|
||||
import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
|
||||
import org.graalvm.compiler.replacements.nodes.BasicObjectCloneNode;
|
||||
|
||||
import jdk.vm.ci.meta.Assumptions;
|
||||
@ -77,11 +77,14 @@ public final class ObjectCloneNode extends BasicObjectCloneNode {
|
||||
@SuppressWarnings("try")
|
||||
protected StructuredGraph getLoweredSnippetGraph(LoweringTool tool) {
|
||||
ResolvedJavaType type = StampTool.typeOrNull(getObject());
|
||||
|
||||
if (type != null) {
|
||||
if (type.isArray()) {
|
||||
Method method = ObjectCloneSnippets.arrayCloneMethods.get(type.getComponentType().getJavaKind());
|
||||
if (method != null) {
|
||||
final ResolvedJavaMethod snippetMethod = tool.getMetaAccess().lookupJavaMethod(method);
|
||||
HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) tool.getLowerer();
|
||||
ObjectCloneSnippets.Templates objectCloneSnippets = lowerer.getObjectCloneSnippets();
|
||||
SnippetInfo info = objectCloneSnippets.arrayCloneMethods.get(type.getComponentType().getJavaKind());
|
||||
if (info != null) {
|
||||
final ResolvedJavaMethod snippetMethod = info.getMethod();
|
||||
final Replacements replacements = tool.getReplacements();
|
||||
StructuredGraph snippetGraph = null;
|
||||
DebugContext debug = getDebug();
|
||||
|
@ -26,40 +26,40 @@ package org.graalvm.compiler.hotspot.replacements;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_VMCONFIG;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.EnumMap;
|
||||
|
||||
import org.graalvm.compiler.api.directives.GraalDirectives;
|
||||
import org.graalvm.compiler.api.replacements.Snippet;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.debug.DebugHandlersFactory;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
|
||||
import org.graalvm.compiler.replacements.arraycopy.ArrayCopyCallNode;
|
||||
import org.graalvm.compiler.nodes.java.DynamicNewArrayNode;
|
||||
import org.graalvm.compiler.nodes.java.NewArrayNode;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates;
|
||||
import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
|
||||
import org.graalvm.compiler.replacements.Snippets;
|
||||
|
||||
import jdk.vm.ci.code.TargetDescription;
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
|
||||
public class ObjectCloneSnippets implements Snippets {
|
||||
|
||||
public static final EnumMap<JavaKind, Method> arrayCloneMethods = new EnumMap<>(JavaKind.class);
|
||||
public static class Templates extends AbstractTemplates {
|
||||
|
||||
static {
|
||||
arrayCloneMethods.put(JavaKind.Boolean, getCloneMethod("booleanArrayClone", boolean[].class));
|
||||
arrayCloneMethods.put(JavaKind.Byte, getCloneMethod("byteArrayClone", byte[].class));
|
||||
arrayCloneMethods.put(JavaKind.Char, getCloneMethod("charArrayClone", char[].class));
|
||||
arrayCloneMethods.put(JavaKind.Short, getCloneMethod("shortArrayClone", short[].class));
|
||||
arrayCloneMethods.put(JavaKind.Int, getCloneMethod("intArrayClone", int[].class));
|
||||
arrayCloneMethods.put(JavaKind.Float, getCloneMethod("floatArrayClone", float[].class));
|
||||
arrayCloneMethods.put(JavaKind.Long, getCloneMethod("longArrayClone", long[].class));
|
||||
arrayCloneMethods.put(JavaKind.Double, getCloneMethod("doubleArrayClone", double[].class));
|
||||
arrayCloneMethods.put(JavaKind.Object, getCloneMethod("objectArrayClone", Object[].class));
|
||||
}
|
||||
final EnumMap<JavaKind, SnippetInfo> arrayCloneMethods = new EnumMap<>(JavaKind.class);
|
||||
|
||||
private static Method getCloneMethod(String name, Class<?> param) {
|
||||
try {
|
||||
return ObjectCloneSnippets.class.getDeclaredMethod(name, param);
|
||||
} catch (SecurityException | NoSuchMethodException e) {
|
||||
throw new GraalError(e);
|
||||
public Templates(OptionValues options, Iterable<DebugHandlersFactory> factories, HotSpotProviders providers, TargetDescription target) {
|
||||
super(options, factories, providers, providers.getSnippetReflection(), target);
|
||||
arrayCloneMethods.put(JavaKind.Boolean, snippet(ObjectCloneSnippets.class, "booleanArrayClone"));
|
||||
arrayCloneMethods.put(JavaKind.Byte, snippet(ObjectCloneSnippets.class, "byteArrayClone"));
|
||||
arrayCloneMethods.put(JavaKind.Char, snippet(ObjectCloneSnippets.class, "charArrayClone"));
|
||||
arrayCloneMethods.put(JavaKind.Short, snippet(ObjectCloneSnippets.class, "shortArrayClone"));
|
||||
arrayCloneMethods.put(JavaKind.Int, snippet(ObjectCloneSnippets.class, "intArrayClone"));
|
||||
arrayCloneMethods.put(JavaKind.Float, snippet(ObjectCloneSnippets.class, "floatArrayClone"));
|
||||
arrayCloneMethods.put(JavaKind.Long, snippet(ObjectCloneSnippets.class, "longArrayClone"));
|
||||
arrayCloneMethods.put(JavaKind.Double, snippet(ObjectCloneSnippets.class, "doubleArrayClone"));
|
||||
arrayCloneMethods.put(JavaKind.Object, snippet(ObjectCloneSnippets.class, "objectArrayClone"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,16 +24,18 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.replacements;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_METAACCESS;
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_INTRINSIC_CONTEXT;
|
||||
import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.ClassSubstitution;
|
||||
import org.graalvm.compiler.api.replacements.Fold;
|
||||
import org.graalvm.compiler.api.replacements.MethodSubstitution;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.hotspot.HotSpotBackend;
|
||||
import org.graalvm.compiler.nodes.ComputeObjectAddressNode;
|
||||
import org.graalvm.compiler.nodes.PiNode;
|
||||
import org.graalvm.compiler.nodes.extended.RawLoadNode;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
|
||||
import org.graalvm.compiler.replacements.ReplacementsUtil;
|
||||
import org.graalvm.compiler.word.Word;
|
||||
import jdk.internal.vm.compiler.word.LocationIdentity;
|
||||
@ -44,31 +46,19 @@ import jdk.vm.ci.meta.JavaKind;
|
||||
@ClassSubstitution(className = "sun.security.provider.SHA2", optional = true)
|
||||
public class SHA2Substitutions {
|
||||
|
||||
static final long stateOffset;
|
||||
|
||||
static final Class<?> shaClass;
|
||||
|
||||
public static final String implCompressName = Java8OrEarlier ? "implCompress" : "implCompress0";
|
||||
|
||||
static {
|
||||
try {
|
||||
// Need to use the system class loader as com.sun.crypto.provider.AESCrypt
|
||||
// is normally loaded by the extension class loader which is not delegated
|
||||
// to by the JVMCI class loader.
|
||||
ClassLoader cl = ClassLoader.getSystemClassLoader();
|
||||
shaClass = Class.forName("sun.security.provider.SHA2", true, cl);
|
||||
stateOffset = UnsafeAccess.UNSAFE.objectFieldOffset(shaClass.getDeclaredField("state"));
|
||||
} catch (Exception ex) {
|
||||
throw new GraalError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@MethodSubstitution(isStatic = false)
|
||||
static void implCompress0(Object receiver, byte[] buf, int ofs) {
|
||||
Object realReceiver = PiNode.piCastNonNull(receiver, shaClass);
|
||||
Object state = RawLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any());
|
||||
Object realReceiver = PiNode.piCastNonNull(receiver, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT));
|
||||
Object state = RawLoadNode.load(realReceiver, stateOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
|
||||
Word bufAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(buf, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte) + ofs));
|
||||
Word stateAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(state, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Int)));
|
||||
HotSpotBackend.sha2ImplCompressStub(bufAddr, stateAddr);
|
||||
}
|
||||
|
||||
@Fold
|
||||
static long stateOffset(@Fold.InjectedParameter IntrinsicContext context) {
|
||||
return HotSpotReplacementsUtil.getFieldOffset(HotSpotReplacementsUtil.methodHolderClass(context), "state");
|
||||
}
|
||||
}
|
||||
|
@ -24,12 +24,12 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.replacements;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_INTRINSIC_CONTEXT;
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
|
||||
import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.ClassSubstitution;
|
||||
import org.graalvm.compiler.api.replacements.MethodSubstitution;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.hotspot.HotSpotBackend;
|
||||
import org.graalvm.compiler.nodes.ComputeObjectAddressNode;
|
||||
import org.graalvm.compiler.nodes.PiNode;
|
||||
@ -44,31 +44,19 @@ import jdk.vm.ci.meta.JavaKind;
|
||||
@ClassSubstitution(className = "sun.security.provider.SHA5", optional = true)
|
||||
public class SHA5Substitutions {
|
||||
|
||||
static final long stateOffset;
|
||||
|
||||
static final Class<?> shaClass;
|
||||
|
||||
public static final String implCompressName = Java8OrEarlier ? "implCompress" : "implCompress0";
|
||||
|
||||
static {
|
||||
try {
|
||||
// Need to use the system class loader as com.sun.crypto.provider.AESCrypt
|
||||
// is normally loaded by the extension class loader which is not delegated
|
||||
// to by the JVMCI class loader.
|
||||
ClassLoader cl = ClassLoader.getSystemClassLoader();
|
||||
shaClass = Class.forName("sun.security.provider.SHA5", true, cl);
|
||||
stateOffset = UnsafeAccess.UNSAFE.objectFieldOffset(shaClass.getDeclaredField("state"));
|
||||
} catch (Exception ex) {
|
||||
throw new GraalError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@MethodSubstitution(isStatic = false)
|
||||
static void implCompress0(Object receiver, byte[] buf, int ofs) {
|
||||
Object realReceiver = PiNode.piCastNonNull(receiver, shaClass);
|
||||
Object state = RawLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any());
|
||||
Object realReceiver = PiNode.piCastNonNull(receiver, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT));
|
||||
Object state = RawLoadNode.load(realReceiver, stateOffset(), JavaKind.Object, LocationIdentity.any());
|
||||
Word bufAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(buf, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte) + ofs));
|
||||
Word stateAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(state, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Int)));
|
||||
HotSpotBackend.sha5ImplCompressStub(bufAddr, stateAddr);
|
||||
}
|
||||
|
||||
static long stateOffset() {
|
||||
return HotSpotReplacementsUtil.getFieldOffset(HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT), "state");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,12 +24,12 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.replacements;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_INTRINSIC_CONTEXT;
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
|
||||
import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.ClassSubstitution;
|
||||
import org.graalvm.compiler.api.replacements.MethodSubstitution;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.hotspot.HotSpotBackend;
|
||||
import org.graalvm.compiler.nodes.ComputeObjectAddressNode;
|
||||
import org.graalvm.compiler.nodes.PiNode;
|
||||
@ -44,31 +44,19 @@ import jdk.vm.ci.meta.JavaKind;
|
||||
@ClassSubstitution(className = "sun.security.provider.SHA", optional = true)
|
||||
public class SHASubstitutions {
|
||||
|
||||
static final long stateOffset;
|
||||
|
||||
static final Class<?> shaClass;
|
||||
|
||||
public static final String implCompressName = Java8OrEarlier ? "implCompress" : "implCompress0";
|
||||
|
||||
static {
|
||||
try {
|
||||
// Need to use the system class loader as com.sun.crypto.provider.AESCrypt
|
||||
// is normally loaded by the extension class loader which is not delegated
|
||||
// to by the JVMCI class loader.
|
||||
ClassLoader cl = ClassLoader.getSystemClassLoader();
|
||||
shaClass = Class.forName("sun.security.provider.SHA", true, cl);
|
||||
stateOffset = UnsafeAccess.UNSAFE.objectFieldOffset(shaClass.getDeclaredField("state"));
|
||||
} catch (Exception ex) {
|
||||
throw new GraalError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@MethodSubstitution(isStatic = false)
|
||||
static void implCompress0(Object receiver, byte[] buf, int ofs) {
|
||||
Object realReceiver = PiNode.piCastNonNull(receiver, shaClass);
|
||||
Object state = RawLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any());
|
||||
Object realReceiver = PiNode.piCastNonNull(receiver, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT));
|
||||
Object state = RawLoadNode.load(realReceiver, stateOffset(), JavaKind.Object, LocationIdentity.any());
|
||||
Word bufAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(buf, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte) + ofs));
|
||||
Word stateAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(state, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Int)));
|
||||
HotSpotBackend.shaImplCompressStub(bufAddr, stateAddr);
|
||||
}
|
||||
|
||||
static long stateOffset() {
|
||||
return HotSpotReplacementsUtil.getFieldOffset(HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT), "state");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,16 +24,17 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.replacements;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.replacements.UnsafeAccess.UNSAFE;
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
|
||||
import static org.graalvm.compiler.replacements.ReplacementsUtil.getArrayBaseOffset;
|
||||
import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.Fold;
|
||||
import org.graalvm.compiler.api.replacements.Snippet;
|
||||
import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
|
||||
import org.graalvm.compiler.debug.DebugHandlersFactory;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
|
||||
import org.graalvm.compiler.nodes.NamedLocationIdentity;
|
||||
import org.graalvm.compiler.nodes.debug.StringToBytesNode;
|
||||
import org.graalvm.compiler.nodes.extended.RawStoreNode;
|
||||
import org.graalvm.compiler.nodes.java.NewArrayNode;
|
||||
import org.graalvm.compiler.nodes.spi.LoweringTool;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
@ -56,11 +57,6 @@ public class StringToBytesSnippets implements Snippets {
|
||||
|
||||
public static final LocationIdentity CSTRING_LOCATION = NamedLocationIdentity.immutable("CString location");
|
||||
|
||||
@Fold
|
||||
static long arrayBaseOffset() {
|
||||
return UNSAFE.arrayBaseOffset(char[].class);
|
||||
}
|
||||
|
||||
@Snippet
|
||||
public static byte[] transform(@ConstantParameter String compilationTimeString) {
|
||||
int i = compilationTimeString.length();
|
||||
@ -68,7 +64,8 @@ public class StringToBytesSnippets implements Snippets {
|
||||
Word cArray = CStringConstant.cstring(compilationTimeString);
|
||||
while (i-- > 0) {
|
||||
// array[i] = cArray.readByte(i);
|
||||
UNSAFE.putByte(array, arrayBaseOffset() + i, cArray.readByte(i, CSTRING_LOCATION));
|
||||
RawStoreNode.storeByte(array, getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte) + i, cArray.readByte(i, CSTRING_LOCATION), JavaKind.Byte,
|
||||
NamedLocationIdentity.getArrayLocation(JavaKind.Byte));
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.replacements;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_METAACCESS;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.referentOffset;
|
||||
import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
|
||||
|
||||
@ -48,7 +49,7 @@ public class UnsafeLoadSnippets implements Snippets {
|
||||
@Snippet
|
||||
public static Object lowerUnsafeLoad(Object object, long offset) {
|
||||
Object fixedObject = FixedValueAnchorNode.getObject(object);
|
||||
if (object instanceof java.lang.ref.Reference && referentOffset() == offset) {
|
||||
if (object instanceof java.lang.ref.Reference && referentOffset(INJECTED_METAACCESS) == offset) {
|
||||
return Word.objectToTrackedPointer(fixedObject).readObject((int) offset, BarrierType.PRECISE);
|
||||
} else {
|
||||
return Word.objectToTrackedPointer(fixedObject).readObject((int) offset, BarrierType.NONE);
|
||||
|
@ -69,6 +69,7 @@ import org.graalvm.compiler.hotspot.nodes.VMErrorNode;
|
||||
import org.graalvm.compiler.nodes.NamedLocationIdentity;
|
||||
import org.graalvm.compiler.nodes.NodeView;
|
||||
import org.graalvm.compiler.nodes.PiNode;
|
||||
import org.graalvm.compiler.nodes.SnippetAnchorNode;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.ValueNode;
|
||||
import org.graalvm.compiler.nodes.extended.FixedValueAnchorNode;
|
||||
@ -313,7 +314,7 @@ public class WriteBarrierSnippets implements Snippets {
|
||||
private static void verifyNotArray(Object object) {
|
||||
if (object != null) {
|
||||
// Manually build the null check and cast because we're in snippet that's lowered late.
|
||||
AssertionNode.assertion(false, !PiNode.piCastNonNull(object, Object.class).getClass().isArray(), "imprecise card mark used with array");
|
||||
AssertionNode.assertion(false, !PiNode.piCastNonNull(object, SnippetAnchorNode.anchor()).getClass().isArray(), "imprecise card mark used with array");
|
||||
}
|
||||
}
|
||||
|
||||
@ -427,7 +428,7 @@ public class WriteBarrierSnippets implements Snippets {
|
||||
private final SnippetInfo serialPreciseWriteBarrier = snippet(WriteBarrierSnippets.class, "serialPreciseWriteBarrier", GC_CARD_LOCATION);
|
||||
private final SnippetInfo serialArrayRangeWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayRangeWriteBarrier");
|
||||
private final SnippetInfo g1PreWriteBarrier = snippet(WriteBarrierSnippets.class, "g1PreWriteBarrier", GC_INDEX_LOCATION, GC_LOG_LOCATION);
|
||||
private final SnippetInfo g1ReferentReadBarrier = snippet(WriteBarrierSnippets.class, "g1PreWriteBarrier", GC_INDEX_LOCATION, GC_LOG_LOCATION);
|
||||
private final SnippetInfo g1ReferentReadBarrier = g1PreWriteBarrier;
|
||||
private final SnippetInfo g1PostWriteBarrier = snippet(WriteBarrierSnippets.class, "g1PostWriteBarrier", GC_CARD_LOCATION, GC_INDEX_LOCATION, GC_LOG_LOCATION);
|
||||
private final SnippetInfo g1ArrayRangePreWriteBarrier = snippet(WriteBarrierSnippets.class, "g1ArrayRangePreWriteBarrier", GC_INDEX_LOCATION, GC_LOG_LOCATION);
|
||||
private final SnippetInfo g1ArrayRangePostWriteBarrier = snippet(WriteBarrierSnippets.class, "g1ArrayRangePostWriteBarrier", GC_CARD_LOCATION, GC_INDEX_LOCATION, GC_LOG_LOCATION);
|
||||
|
@ -25,7 +25,10 @@
|
||||
package org.graalvm.compiler.hotspot.replacements.profiling;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.config;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.backedgeCounterOffset;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.invocationCounterIncrement;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.invocationCounterOffset;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.invocationCounterShift;
|
||||
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY;
|
||||
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
|
||||
import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
|
||||
@ -79,11 +82,11 @@ public class ProbabilisticProfileSnippets implements Snippets {
|
||||
@Snippet
|
||||
public static void profileMethodEntryWithProbability(MethodCountersPointer counters, int random, int step, int stepLog, @ConstantParameter int freqLog, @ConstantParameter int probLog) {
|
||||
if (probability(1.0 / (1 << probLog), shouldProfile(probLog, random))) {
|
||||
int counterValue = counters.readInt(config(INJECTED_VMCONFIG).invocationCounterOffset) + ((config(INJECTED_VMCONFIG).invocationCounterIncrement * step) << probLog);
|
||||
counters.writeInt(config(INJECTED_VMCONFIG).invocationCounterOffset, counterValue);
|
||||
int counterValue = counters.readInt(invocationCounterOffset(INJECTED_VMCONFIG)) + ((invocationCounterIncrement(INJECTED_VMCONFIG) * step) << probLog);
|
||||
counters.writeInt(invocationCounterOffset(INJECTED_VMCONFIG), counterValue);
|
||||
if (freqLog >= 0) {
|
||||
int mask = notificationMask(freqLog, probLog, stepLog);
|
||||
if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << config(INJECTED_VMCONFIG).invocationCounterShift)) == 0)) {
|
||||
if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << invocationCounterShift(INJECTED_VMCONFIG))) == 0)) {
|
||||
methodInvocationEvent(HotSpotBackend.INVOCATION_EVENT, counters);
|
||||
}
|
||||
}
|
||||
@ -97,10 +100,10 @@ public class ProbabilisticProfileSnippets implements Snippets {
|
||||
public static void profileBackedgeWithProbability(MethodCountersPointer counters, int random, int step, int stepLog, @ConstantParameter int freqLog, @ConstantParameter int probLog, int bci,
|
||||
int targetBci) {
|
||||
if (probability(1.0 / (1 << probLog), shouldProfile(probLog, random))) {
|
||||
int counterValue = counters.readInt(config(INJECTED_VMCONFIG).backedgeCounterOffset) + ((config(INJECTED_VMCONFIG).invocationCounterIncrement * step) << probLog);
|
||||
counters.writeInt(config(INJECTED_VMCONFIG).backedgeCounterOffset, counterValue);
|
||||
int counterValue = counters.readInt(backedgeCounterOffset(INJECTED_VMCONFIG)) + ((invocationCounterIncrement(INJECTED_VMCONFIG) * step) << probLog);
|
||||
counters.writeInt(backedgeCounterOffset(INJECTED_VMCONFIG), counterValue);
|
||||
int mask = notificationMask(freqLog, probLog, stepLog);
|
||||
if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << config(INJECTED_VMCONFIG).invocationCounterShift)) == 0)) {
|
||||
if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << invocationCounterShift(INJECTED_VMCONFIG))) == 0)) {
|
||||
methodBackedgeEvent(HotSpotBackend.BACKEDGE_EVENT, counters, bci, targetBci);
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,10 @@
|
||||
package org.graalvm.compiler.hotspot.replacements.profiling;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.config;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.backedgeCounterOffset;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.invocationCounterIncrement;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.invocationCounterOffset;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.invocationCounterShift;
|
||||
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY;
|
||||
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
|
||||
import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
|
||||
@ -72,11 +75,11 @@ public class ProfileSnippets implements Snippets {
|
||||
|
||||
@Snippet
|
||||
public static void profileMethodEntry(MethodCountersPointer counters, int step, int stepLog, @ConstantParameter int freqLog) {
|
||||
int counterValue = counters.readInt(config(INJECTED_VMCONFIG).invocationCounterOffset) + config(INJECTED_VMCONFIG).invocationCounterIncrement * step;
|
||||
counters.writeInt(config(INJECTED_VMCONFIG).invocationCounterOffset, counterValue);
|
||||
int counterValue = counters.readInt(invocationCounterOffset(INJECTED_VMCONFIG)) + invocationCounterIncrement(INJECTED_VMCONFIG) * step;
|
||||
counters.writeInt(invocationCounterOffset(INJECTED_VMCONFIG), counterValue);
|
||||
if (freqLog >= 0) {
|
||||
final int mask = notificationMask(freqLog, stepLog);
|
||||
if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << config(INJECTED_VMCONFIG).invocationCounterShift)) == 0)) {
|
||||
if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << invocationCounterShift(INJECTED_VMCONFIG))) == 0)) {
|
||||
methodInvocationEvent(HotSpotBackend.INVOCATION_EVENT, counters);
|
||||
}
|
||||
}
|
||||
@ -87,10 +90,10 @@ public class ProfileSnippets implements Snippets {
|
||||
|
||||
@Snippet
|
||||
public static void profileBackedge(MethodCountersPointer counters, int step, int stepLog, @ConstantParameter int freqLog, int bci, int targetBci) {
|
||||
int counterValue = counters.readInt(config(INJECTED_VMCONFIG).backedgeCounterOffset) + config(INJECTED_VMCONFIG).invocationCounterIncrement * step;
|
||||
counters.writeInt(config(INJECTED_VMCONFIG).backedgeCounterOffset, counterValue);
|
||||
int counterValue = counters.readInt(backedgeCounterOffset(INJECTED_VMCONFIG)) + invocationCounterIncrement(INJECTED_VMCONFIG) * step;
|
||||
counters.writeInt(backedgeCounterOffset(INJECTED_VMCONFIG), counterValue);
|
||||
final int mask = notificationMask(freqLog, stepLog);
|
||||
if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << config(INJECTED_VMCONFIG).invocationCounterShift)) == 0)) {
|
||||
if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << invocationCounterShift(INJECTED_VMCONFIG))) == 0)) {
|
||||
methodBackedgeEvent(HotSpotBackend.BACKEDGE_EVENT, counters, bci, targetBci);
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ import org.graalvm.compiler.hotspot.word.KlassPointer;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.replacements.nodes.CStringConstant;
|
||||
import org.graalvm.compiler.word.Word;
|
||||
import jdk.internal.vm.compiler.word.WordFactory;
|
||||
|
||||
import jdk.vm.ci.code.Register;
|
||||
|
||||
@ -67,7 +68,7 @@ public class CreateExceptionStub extends SnippetStub {
|
||||
}
|
||||
|
||||
protected static Object createException(Register threadRegister, Class<? extends Throwable> exception) {
|
||||
Word message = null;
|
||||
Word message = WordFactory.zero();
|
||||
return createException(threadRegister, exception, message);
|
||||
}
|
||||
|
||||
|
@ -87,17 +87,17 @@ public class ExceptionHandlerStub extends SnippetStub {
|
||||
return providers.getRegisters().getThreadRegister();
|
||||
}
|
||||
assert index == 3;
|
||||
return options;
|
||||
return StubOptions.TraceExceptionHandlerStub.getValue(options);
|
||||
}
|
||||
|
||||
@Snippet
|
||||
private static void exceptionHandler(Object exception, Word exceptionPc, @ConstantParameter Register threadRegister, @ConstantParameter OptionValues options) {
|
||||
private static void exceptionHandler(Object exception, Word exceptionPc, @ConstantParameter Register threadRegister, @ConstantParameter boolean logging) {
|
||||
Word thread = registerAsWord(threadRegister);
|
||||
checkNoExceptionInThread(thread, assertionsEnabled(INJECTED_VMCONFIG));
|
||||
checkExceptionNotNull(assertionsEnabled(INJECTED_VMCONFIG), exception);
|
||||
writeExceptionOop(thread, exception);
|
||||
writeExceptionPc(thread, exceptionPc);
|
||||
if (logging(options)) {
|
||||
if (logging) {
|
||||
printf("handling exception %p (", Word.objectToTrackedPointer(exception).rawValue());
|
||||
decipher(Word.objectToTrackedPointer(exception).rawValue());
|
||||
printf(") at %p (", exceptionPc.rawValue());
|
||||
@ -110,7 +110,7 @@ public class ExceptionHandlerStub extends SnippetStub {
|
||||
|
||||
Word handlerPc = exceptionHandlerForPc(EXCEPTION_HANDLER_FOR_PC, thread);
|
||||
|
||||
if (logging(options)) {
|
||||
if (logging) {
|
||||
printf("handler for exception %p at %p is at %p (", Word.objectToTrackedPointer(exception).rawValue(), exceptionPc.rawValue(), handlerPc.rawValue());
|
||||
decipher(handlerPc.rawValue());
|
||||
printf(")\n");
|
||||
@ -143,11 +143,6 @@ public class ExceptionHandlerStub extends SnippetStub {
|
||||
}
|
||||
}
|
||||
|
||||
@Fold
|
||||
static boolean logging(OptionValues options) {
|
||||
return StubOptions.TraceExceptionHandlerStub.getValue(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if either Java assertions are enabled for Graal or if this is a HotSpot build
|
||||
* where the ASSERT mechanism is enabled.
|
||||
|
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2018, 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.
|
||||
*
|
||||
* 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 org.graalvm.compiler.hotspot.stubs;
|
||||
|
||||
import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_VMCONFIG;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.clearPendingException;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getPendingException;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadHubIntrinsic;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.verifyOops;
|
||||
import static org.graalvm.compiler.hotspot.stubs.StubUtil.fatal;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.Fold;
|
||||
import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
|
||||
import org.graalvm.compiler.api.replacements.Snippet;
|
||||
import org.graalvm.compiler.debug.DebugHandlersFactory;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
|
||||
import org.graalvm.compiler.hotspot.nodes.DeoptimizeCallerNode;
|
||||
import org.graalvm.compiler.hotspot.word.KlassPointer;
|
||||
import org.graalvm.compiler.nodes.NamedLocationIdentity;
|
||||
import org.graalvm.compiler.nodes.PiNode;
|
||||
import org.graalvm.compiler.nodes.SnippetAnchorNode;
|
||||
import org.graalvm.compiler.nodes.extended.GuardingNode;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates;
|
||||
import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
|
||||
import org.graalvm.compiler.replacements.Snippets;
|
||||
import org.graalvm.compiler.word.Word;
|
||||
import jdk.internal.vm.compiler.word.LocationIdentity;
|
||||
import jdk.internal.vm.compiler.word.Pointer;
|
||||
import jdk.internal.vm.compiler.word.WordFactory;
|
||||
|
||||
import jdk.vm.ci.code.TargetDescription;
|
||||
import jdk.vm.ci.meta.DeoptimizationAction;
|
||||
|
||||
public class ForeignCallSnippets implements Snippets {
|
||||
|
||||
public static class Templates extends AbstractTemplates {
|
||||
|
||||
final SnippetInfo handlePendingException = snippet(ForeignCallSnippets.class, "handlePendingException");
|
||||
final SnippetInfo getAndClearObjectResult = snippet(ForeignCallSnippets.class, "getAndClearObjectResult", OBJECT_RESULT_LOCATION);
|
||||
final SnippetInfo verifyObject = snippet(ForeignCallSnippets.class, "verifyObject");
|
||||
|
||||
public Templates(OptionValues options, Iterable<DebugHandlersFactory> factories, HotSpotProviders providers, TargetDescription target) {
|
||||
super(options, factories, providers, providers.getSnippetReflection(), target);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link ForeignCallStub#getGraph}.
|
||||
*/
|
||||
@Snippet
|
||||
public static void handlePendingException(Word thread, boolean shouldClearException, boolean isObjectResult) {
|
||||
if ((shouldClearException && clearPendingException(thread) != null) || (!shouldClearException && getPendingException(thread) != null)) {
|
||||
if (isObjectResult) {
|
||||
getAndClearObjectResult(thread);
|
||||
}
|
||||
DeoptimizeCallerNode.deopt(DeoptimizationAction.None, RuntimeConstraint);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a given object value is well formed if {@code -XX:+VerifyOops} is enabled.
|
||||
*/
|
||||
@Snippet
|
||||
public static Object verifyObject(Object object) {
|
||||
if (verifyOops(INJECTED_VMCONFIG)) {
|
||||
Word verifyOopCounter = WordFactory.unsigned(verifyOopCounterAddress(INJECTED_VMCONFIG));
|
||||
verifyOopCounter.writeInt(0, verifyOopCounter.readInt(0) + 1);
|
||||
|
||||
Pointer oop = Word.objectToTrackedPointer(object);
|
||||
if (object != null) {
|
||||
GuardingNode anchorNode = SnippetAnchorNode.anchor();
|
||||
// make sure object is 'reasonable'
|
||||
if (!oop.and(WordFactory.unsigned(verifyOopMask(INJECTED_VMCONFIG))).equal(WordFactory.unsigned(verifyOopBits(INJECTED_VMCONFIG)))) {
|
||||
fatal("oop not in heap: %p", oop.rawValue());
|
||||
}
|
||||
|
||||
KlassPointer klass = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode));
|
||||
if (klass.isNull()) {
|
||||
fatal("klass for oop %p is null", oop.rawValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
@Fold
|
||||
static long verifyOopCounterAddress(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.verifyOopCounterAddress;
|
||||
}
|
||||
|
||||
@Fold
|
||||
static long verifyOopMask(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.verifyOopMask;
|
||||
}
|
||||
|
||||
@Fold
|
||||
static long verifyOopBits(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.verifyOopBits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets and clears the object result from a runtime call stored in a thread local.
|
||||
*
|
||||
* @return the object that was in the thread local
|
||||
*/
|
||||
@Snippet
|
||||
public static Object getAndClearObjectResult(Word thread) {
|
||||
Object result = thread.readObject(objectResultOffset(INJECTED_VMCONFIG), OBJECT_RESULT_LOCATION);
|
||||
thread.writeObject(objectResultOffset(INJECTED_VMCONFIG), null, OBJECT_RESULT_LOCATION);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static final LocationIdentity OBJECT_RESULT_LOCATION = NamedLocationIdentity.mutable("ObjectResult");
|
||||
|
||||
@Fold
|
||||
static int objectResultOffset(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.threadObjectResultOffset;
|
||||
}
|
||||
}
|
@ -24,11 +24,14 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.stubs;
|
||||
|
||||
import static jdk.vm.ci.code.BytecodeFrame.UNKNOWN_BCI;
|
||||
import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCall;
|
||||
import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCallee;
|
||||
import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS;
|
||||
import static org.graalvm.compiler.nodes.CallTargetNode.InvokeKind.Static;
|
||||
import static org.graalvm.compiler.nodes.ConstantNode.forBoolean;
|
||||
|
||||
import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||
import org.graalvm.compiler.core.common.LIRKind;
|
||||
@ -43,10 +46,10 @@ import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
|
||||
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability;
|
||||
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition;
|
||||
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotLoweringProvider;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
|
||||
import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode;
|
||||
import org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil;
|
||||
import org.graalvm.compiler.nodes.ConstantNode;
|
||||
import org.graalvm.compiler.hotspot.stubs.ForeignCallSnippets.Templates;
|
||||
import org.graalvm.compiler.nodes.InvokeNode;
|
||||
import org.graalvm.compiler.nodes.ParameterNode;
|
||||
import org.graalvm.compiler.nodes.ReturnNode;
|
||||
@ -76,8 +79,8 @@ import jdk.vm.ci.meta.Signature;
|
||||
* deoptimization while the call is in progress. And since these are foreign/runtime calls on slow
|
||||
* paths, we don't want to force the register allocator to spill around the call. As such, this stub
|
||||
* saves and restores all allocatable registers. It also
|
||||
* {@linkplain StubUtil#handlePendingException(Word, boolean, boolean) handles} any exceptions
|
||||
* raised during the foreign call.
|
||||
* {@linkplain ForeignCallSnippets#handlePendingException handles} any exceptions raised during the
|
||||
* foreign call.
|
||||
*/
|
||||
public class ForeignCallStub extends Stub {
|
||||
|
||||
@ -112,9 +115,10 @@ public class ForeignCallStub extends Stub {
|
||||
PRESERVES_REGISTERS, JavaCall, JavaCallee, transition, reexecutability, killedLocations));
|
||||
this.jvmciRuntime = runtime;
|
||||
this.prependThread = prependThread;
|
||||
MetaAccessProvider metaAccess = providers.getMetaAccess();
|
||||
Class<?>[] targetParameterTypes = createTargetParameters(descriptor);
|
||||
ForeignCallDescriptor targetSig = new ForeignCallDescriptor(descriptor.getName() + ":C", descriptor.getResultType(), targetParameterTypes);
|
||||
target = HotSpotForeignCallLinkageImpl.create(providers.getMetaAccess(), providers.getCodeCache(), providers.getWordTypes(), providers.getForeignCalls(), targetSig, address,
|
||||
target = HotSpotForeignCallLinkageImpl.create(metaAccess, providers.getCodeCache(), providers.getWordTypes(), providers.getForeignCalls(), targetSig, address,
|
||||
DESTROYS_REGISTERS, NativeCall, NativeCall, transition, reexecutability, killedLocations);
|
||||
}
|
||||
|
||||
@ -234,16 +238,21 @@ public class ForeignCallStub extends Stub {
|
||||
// Do we want to clear the pending exception?
|
||||
boolean shouldClearException = linkage.isReexecutable() || linkage.isReexecutableOnlyAfterException();
|
||||
try {
|
||||
ResolvedJavaMethod thisMethod = providers.getMetaAccess().lookupJavaMethod(ForeignCallStub.class.getDeclaredMethod("getGraph", DebugContext.class, CompilationIdentifier.class));
|
||||
HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer();
|
||||
Templates foreignCallSnippets = lowerer.getForeignCallSnippets();
|
||||
ResolvedJavaMethod handlePendingException = foreignCallSnippets.handlePendingException.getMethod();
|
||||
ResolvedJavaMethod getAndClearObjectResult = foreignCallSnippets.getAndClearObjectResult.getMethod();
|
||||
ResolvedJavaMethod verifyObject = foreignCallSnippets.verifyObject.getMethod();
|
||||
ResolvedJavaMethod thisMethod = getGraphMethod();
|
||||
GraphKit kit = new GraphKit(debug, thisMethod, providers, wordTypes, providers.getGraphBuilderPlugins(), compilationId, toString());
|
||||
StructuredGraph graph = kit.getGraph();
|
||||
ParameterNode[] params = createParameters(kit, args);
|
||||
ReadRegisterNode thread = kit.append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), wordTypes.getWordKind(), true, false));
|
||||
ValueNode result = createTargetCall(kit, params, thread);
|
||||
kit.createInvoke(StubUtil.class, "handlePendingException", thread, ConstantNode.forBoolean(shouldClearException, graph), ConstantNode.forBoolean(isObjectResult, graph));
|
||||
createStaticInvoke(kit, handlePendingException, thread, forBoolean(shouldClearException, graph), forBoolean(isObjectResult, graph));
|
||||
if (isObjectResult) {
|
||||
InvokeNode object = kit.createInvoke(HotSpotReplacementsUtil.class, "getAndClearObjectResult", thread);
|
||||
result = kit.createInvoke(StubUtil.class, "verifyObject", object);
|
||||
InvokeNode object = createStaticInvoke(kit, getAndClearObjectResult, thread);
|
||||
result = createStaticInvoke(kit, verifyObject, object);
|
||||
}
|
||||
kit.append(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result));
|
||||
debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Initial stub graph");
|
||||
@ -258,6 +267,27 @@ public class ForeignCallStub extends Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private static InvokeNode createStaticInvoke(GraphKit kit, ResolvedJavaMethod method, ValueNode... args) {
|
||||
return kit.createInvoke(method, Static, null, UNKNOWN_BCI, args);
|
||||
}
|
||||
|
||||
private ResolvedJavaMethod getGraphMethod() {
|
||||
ResolvedJavaMethod thisMethod = null;
|
||||
for (ResolvedJavaMethod method : providers.getMetaAccess().lookupJavaType(ForeignCallStub.class).getDeclaredMethods()) {
|
||||
if (method.getName().equals("getGraph")) {
|
||||
if (thisMethod == null) {
|
||||
thisMethod = method;
|
||||
} else {
|
||||
throw new InternalError("getGraph is ambiguous");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (thisMethod == null) {
|
||||
throw new InternalError("Can't find getGraph");
|
||||
}
|
||||
return thisMethod;
|
||||
}
|
||||
|
||||
private ParameterNode[] createParameters(GraphKit kit, Class<?>[] args) {
|
||||
ParameterNode[] params = new ParameterNode[args.length];
|
||||
ResolvedJavaType accessingClass = providers.getMetaAccess().lookupJavaType(getClass());
|
||||
|
@ -24,43 +24,30 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.stubs;
|
||||
|
||||
import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.Snippet;
|
||||
import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
|
||||
import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter;
|
||||
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
|
||||
import org.graalvm.compiler.bytecode.BytecodeProvider;
|
||||
import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||
import org.graalvm.compiler.core.common.type.StampFactory;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
|
||||
import org.graalvm.compiler.java.GraphBuilderPhase;
|
||||
import org.graalvm.compiler.nodes.NodeView;
|
||||
import org.graalvm.compiler.nodes.ParameterNode;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
|
||||
import org.graalvm.compiler.nodes.spi.LoweringTool;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.phases.OptimisticOptimizations;
|
||||
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
|
||||
import org.graalvm.compiler.phases.common.LoweringPhase;
|
||||
import org.graalvm.compiler.phases.common.RemoveValueProxyPhase;
|
||||
import org.graalvm.compiler.phases.tiers.PhaseContext;
|
||||
import org.graalvm.compiler.replacements.ConstantBindingParameterPlugin;
|
||||
import org.graalvm.compiler.replacements.SnippetTemplate;
|
||||
import org.graalvm.compiler.replacements.Snippets;
|
||||
|
||||
import jdk.vm.ci.meta.Local;
|
||||
import jdk.vm.ci.meta.LocalVariableTable;
|
||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
/**
|
||||
@ -92,40 +79,21 @@ public abstract class SnippetStub extends Stub implements Snippets {
|
||||
*/
|
||||
public SnippetStub(Class<? extends Snippets> snippetDeclaringClass, String snippetMethodName, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
|
||||
super(options, providers, linkage);
|
||||
Method javaMethod = SnippetTemplate.AbstractTemplates.findMethod(snippetDeclaringClass == null ? getClass() : snippetDeclaringClass, snippetMethodName, null);
|
||||
this.method = providers.getMetaAccess().lookupJavaMethod(javaMethod);
|
||||
this.method = SnippetTemplate.AbstractTemplates.findMethod(providers.getMetaAccess(), snippetDeclaringClass == null ? getClass() : snippetDeclaringClass, snippetMethodName);
|
||||
registerSnippet();
|
||||
}
|
||||
|
||||
protected void registerSnippet() {
|
||||
providers.getReplacements().registerSnippet(method, null, null, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("try")
|
||||
protected StructuredGraph getGraph(DebugContext debug, CompilationIdentifier compilationId) {
|
||||
Plugins defaultPlugins = providers.getGraphBuilderPlugins();
|
||||
MetaAccessProvider metaAccess = providers.getMetaAccess();
|
||||
SnippetReflectionProvider snippetReflection = providers.getSnippetReflection();
|
||||
|
||||
Plugins plugins = new Plugins(defaultPlugins);
|
||||
plugins.prependParameterPlugin(new ConstantBindingParameterPlugin(makeConstArgs(), metaAccess, snippetReflection));
|
||||
GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins);
|
||||
|
||||
// @formatter:off
|
||||
// Stubs cannot have optimistic assumptions since they have
|
||||
// to be valid for the entire run of the VM.
|
||||
final StructuredGraph graph = new StructuredGraph.Builder(options, debug).
|
||||
method(method).
|
||||
compilationId(compilationId).
|
||||
setIsSubstitution(true).
|
||||
build();
|
||||
// @formatter:on
|
||||
final StructuredGraph graph = buildInitialGraph(debug, compilationId, makeConstArgs());
|
||||
try (DebugContext.Scope outer = debug.scope("SnippetStub", graph)) {
|
||||
graph.disableUnsafeAccessTracking();
|
||||
|
||||
IntrinsicContext initialIntrinsicContext = new IntrinsicContext(method, method, getReplacementsBytecodeProvider(), INLINE_AFTER_PARSING);
|
||||
GraphBuilderPhase.Instance instance = new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(),
|
||||
providers.getConstantReflection(), providers.getConstantFieldProvider(),
|
||||
config, OptimisticOptimizations.NONE,
|
||||
initialIntrinsicContext);
|
||||
instance.apply(graph);
|
||||
|
||||
for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) {
|
||||
int index = param.index();
|
||||
if (method.getParameterAnnotation(NonNullParameter.class, index) != null) {
|
||||
@ -146,8 +114,8 @@ public abstract class SnippetStub extends Stub implements Snippets {
|
||||
return graph;
|
||||
}
|
||||
|
||||
protected BytecodeProvider getReplacementsBytecodeProvider() {
|
||||
return providers.getReplacements().getDefaultReplacementBytecodeProvider();
|
||||
protected StructuredGraph buildInitialGraph(DebugContext debug, CompilationIdentifier compilationId, Object[] args) {
|
||||
return providers.getReplacements().getSnippet(method, args, false, null).copyWithIdentifier(compilationId, debug);
|
||||
}
|
||||
|
||||
protected boolean checkConstArg(int index, String expectedName) {
|
||||
@ -191,4 +159,8 @@ public abstract class SnippetStub extends Stub implements Snippets {
|
||||
public String toString() {
|
||||
return "Stub<" + getInstalledCodeOwner().format("%h.%n") + ">";
|
||||
}
|
||||
|
||||
public ResolvedJavaMethod getMethod() {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
@ -24,13 +24,6 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.stubs;
|
||||
|
||||
import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_VMCONFIG;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.clearPendingException;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getPendingException;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getAndClearObjectResult;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadHubIntrinsic;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.verifyOops;
|
||||
import static org.graalvm.compiler.replacements.nodes.CStringConstant.cstring;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
@ -44,20 +37,12 @@ import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
|
||||
import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
|
||||
import org.graalvm.compiler.graph.Node.NodeIntrinsic;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.hotspot.nodes.DeoptimizeCallerNode;
|
||||
import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode;
|
||||
import org.graalvm.compiler.hotspot.nodes.VMErrorNode;
|
||||
import org.graalvm.compiler.hotspot.word.KlassPointer;
|
||||
import org.graalvm.compiler.nodes.PiNode;
|
||||
import org.graalvm.compiler.nodes.SnippetAnchorNode;
|
||||
import org.graalvm.compiler.nodes.extended.GuardingNode;
|
||||
import org.graalvm.compiler.replacements.Log;
|
||||
import org.graalvm.compiler.word.Word;
|
||||
import jdk.internal.vm.compiler.word.Pointer;
|
||||
import jdk.internal.vm.compiler.word.WordFactory;
|
||||
|
||||
import jdk.vm.ci.meta.DeoptimizationAction;
|
||||
|
||||
//JaCoCo Exclude
|
||||
|
||||
/**
|
||||
@ -96,15 +81,6 @@ public class StubUtil {
|
||||
return new ForeignCallDescriptor(name, found.getReturnType(), cCallTypes);
|
||||
}
|
||||
|
||||
public static void handlePendingException(Word thread, boolean shouldClearException, boolean isObjectResult) {
|
||||
if ((shouldClearException && clearPendingException(thread) != null) || (!shouldClearException && getPendingException(thread) != null)) {
|
||||
if (isObjectResult) {
|
||||
getAndClearObjectResult(thread);
|
||||
}
|
||||
DeoptimizeCallerNode.deopt(DeoptimizationAction.None, RuntimeConstraint);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if this is a HotSpot build where the ASSERT mechanism is enabled.
|
||||
*/
|
||||
@ -231,46 +207,6 @@ public class StubUtil {
|
||||
vmMessageC(VM_MESSAGE_C, true, cstring(format), v1, v2, v3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a given object value is well formed if {@code -XX:+VerifyOops} is enabled.
|
||||
*/
|
||||
public static Object verifyObject(Object object) {
|
||||
if (verifyOops(INJECTED_VMCONFIG)) {
|
||||
Word verifyOopCounter = WordFactory.unsigned(verifyOopCounterAddress(INJECTED_VMCONFIG));
|
||||
verifyOopCounter.writeInt(0, verifyOopCounter.readInt(0) + 1);
|
||||
|
||||
Pointer oop = Word.objectToTrackedPointer(object);
|
||||
if (object != null) {
|
||||
GuardingNode anchorNode = SnippetAnchorNode.anchor();
|
||||
// make sure object is 'reasonable'
|
||||
if (!oop.and(WordFactory.unsigned(verifyOopMask(INJECTED_VMCONFIG))).equal(WordFactory.unsigned(verifyOopBits(INJECTED_VMCONFIG)))) {
|
||||
fatal("oop not in heap: %p", oop.rawValue());
|
||||
}
|
||||
|
||||
KlassPointer klass = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode));
|
||||
if (klass.isNull()) {
|
||||
fatal("klass for oop %p is null", oop.rawValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
@Fold
|
||||
static long verifyOopCounterAddress(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.verifyOopCounterAddress;
|
||||
}
|
||||
|
||||
@Fold
|
||||
static long verifyOopMask(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.verifyOopMask;
|
||||
}
|
||||
|
||||
@Fold
|
||||
static long verifyOopBits(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||
return config.verifyOopBits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print {@code number} as decimal string to {@code buffer}.
|
||||
*
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.stubs;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_OPTIONVALUES;
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
|
||||
import static org.graalvm.compiler.hotspot.nodes.JumpToExceptionHandlerInCallerNode.jumpToExceptionHandlerInCaller;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord;
|
||||
@ -77,14 +78,13 @@ public class UnwindExceptionToCallerStub extends SnippetStub {
|
||||
if (index == 2) {
|
||||
return providers.getRegisters().getThreadRegister();
|
||||
}
|
||||
assert index == 3;
|
||||
return options;
|
||||
throw new InternalError();
|
||||
}
|
||||
|
||||
@Snippet
|
||||
private static void unwindExceptionToCaller(Object exception, Word returnAddress, @ConstantParameter Register threadRegister, @ConstantParameter OptionValues options) {
|
||||
private static void unwindExceptionToCaller(Object exception, Word returnAddress, @ConstantParameter Register threadRegister) {
|
||||
Pointer exceptionOop = Word.objectToTrackedPointer(exception);
|
||||
if (logging(options)) {
|
||||
if (logging(INJECTED_OPTIONVALUES)) {
|
||||
printf("unwinding exception %p (", exceptionOop.rawValue());
|
||||
decipher(exceptionOop.rawValue());
|
||||
printf(") at %p (", returnAddress.rawValue());
|
||||
@ -97,7 +97,7 @@ public class UnwindExceptionToCallerStub extends SnippetStub {
|
||||
|
||||
Word handlerInCallerPc = exceptionHandlerForReturnAddress(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, thread, returnAddress);
|
||||
|
||||
if (logging(options)) {
|
||||
if (logging(INJECTED_OPTIONVALUES)) {
|
||||
printf("handler for exception %p at return address %p is at %p (", exceptionOop.rawValue(), returnAddress.rawValue(), handlerInCallerPc.rawValue());
|
||||
decipher(handlerInCallerPc.rawValue());
|
||||
printf(")\n");
|
||||
@ -107,7 +107,7 @@ public class UnwindExceptionToCallerStub extends SnippetStub {
|
||||
}
|
||||
|
||||
@Fold
|
||||
static boolean logging(OptionValues options) {
|
||||
static boolean logging(@Fold.InjectedParameter OptionValues options) {
|
||||
return StubOptions.TraceUnwindStub.getValue(options);
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.stubs;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.stubs.StubUtil.verifyObject;
|
||||
import static org.graalvm.compiler.hotspot.stubs.ForeignCallSnippets.verifyObject;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.Snippet;
|
||||
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
|
||||
|
@ -38,11 +38,11 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
* {@link GraphEncoder} for a description of the encoding format. Use {@link GraphDecoder} for
|
||||
* decoding.
|
||||
*/
|
||||
public final class EncodedGraph {
|
||||
public class EncodedGraph {
|
||||
|
||||
private final byte[] encoding;
|
||||
private final int startOffset;
|
||||
private final Object[] objects;
|
||||
protected final Object[] objects;
|
||||
private final NodeClass<?>[] types;
|
||||
private final Assumptions assumptions;
|
||||
private final List<ResolvedJavaMethod> inlinedMethods;
|
||||
@ -82,10 +82,18 @@ public final class EncodedGraph {
|
||||
return startOffset;
|
||||
}
|
||||
|
||||
public Object[] getObjects() {
|
||||
protected Object[] getObjects() {
|
||||
return objects;
|
||||
}
|
||||
|
||||
public int getNumObjects() {
|
||||
return objects.length;
|
||||
}
|
||||
|
||||
public Object getObject(int i) {
|
||||
return objects[i];
|
||||
}
|
||||
|
||||
public NodeClass<?>[] getNodeClasses() {
|
||||
return types;
|
||||
}
|
||||
@ -109,4 +117,9 @@ public final class EncodedGraph {
|
||||
public boolean hasUnsafeAccess() {
|
||||
return hasUnsafeAccess;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public boolean isCallToOriginal(ResolvedJavaMethod callTarget) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -27,8 +27,6 @@ package org.graalvm.compiler.nodes;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0;
|
||||
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
|
||||
import org.graalvm.compiler.core.common.type.ObjectStamp;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
@ -51,10 +49,12 @@ import org.graalvm.compiler.nodes.spi.VirtualizerTool;
|
||||
import org.graalvm.compiler.nodes.type.StampTool;
|
||||
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
|
||||
|
||||
//JaCoCo Exclude
|
||||
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
|
||||
//JaCoCo Exclude
|
||||
|
||||
/**
|
||||
* A node that changes the type of its input, usually narrowing it. For example, a {@link PiNode}
|
||||
* refines the type of a receiver during type-guarded inlining to be the type tested by the guard.
|
||||
@ -281,12 +281,12 @@ public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtual
|
||||
* Changes the stamp of an object to represent a given type and to indicate that the object is
|
||||
* not null.
|
||||
*/
|
||||
public static Object piCastNonNull(Object object, @ConstantNodeParameter Class<?> toType) {
|
||||
public static Object piCastNonNull(Object object, @ConstantNodeParameter ResolvedJavaType toType) {
|
||||
return piCast(object, toType, false, true);
|
||||
}
|
||||
|
||||
@NodeIntrinsic
|
||||
public static native Object piCast(Object object, @ConstantNodeParameter Class<?> toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull);
|
||||
public static native Object piCast(Object object, @ConstantNodeParameter ResolvedJavaType toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull);
|
||||
|
||||
/**
|
||||
* A placeholder node in a snippet that will be replaced with a {@link PiNode} when the snippet
|
||||
|
@ -83,6 +83,9 @@ public final class RawStoreNode extends UnsafeAccessNode implements StateSplit,
|
||||
@NodeIntrinsic
|
||||
public static native Object storeChar(Object object, long offset, char value, @ConstantNodeParameter JavaKind kind, @ConstantNodeParameter LocationIdentity locationIdentity);
|
||||
|
||||
@NodeIntrinsic
|
||||
public static native Object storeByte(Object object, long offset, byte value, @ConstantNodeParameter JavaKind kind, @ConstantNodeParameter LocationIdentity locationIdentity);
|
||||
|
||||
public boolean needsBarrier() {
|
||||
return needsBarrier;
|
||||
}
|
||||
|
@ -43,15 +43,20 @@ import org.graalvm.compiler.nodes.LogicNode;
|
||||
import org.graalvm.compiler.nodes.NodeView;
|
||||
import org.graalvm.compiler.nodes.UnaryOpLogicNode;
|
||||
import org.graalvm.compiler.nodes.ValueNode;
|
||||
import org.graalvm.compiler.nodes.calc.ConditionalNode;
|
||||
import org.graalvm.compiler.nodes.calc.IsNullNode;
|
||||
import org.graalvm.compiler.nodes.extended.AnchoringNode;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
|
||||
import org.graalvm.compiler.nodes.spi.Lowerable;
|
||||
import org.graalvm.compiler.nodes.spi.LoweringTool;
|
||||
import org.graalvm.compiler.nodes.spi.Virtualizable;
|
||||
import org.graalvm.compiler.nodes.spi.VirtualizerTool;
|
||||
import org.graalvm.compiler.nodes.type.StampTool;
|
||||
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.JavaTypeProfile;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
import jdk.vm.ci.meta.TriState;
|
||||
|
||||
/**
|
||||
@ -218,6 +223,17 @@ public class InstanceOfNode extends UnaryOpLogicNode implements Lowerable, Virtu
|
||||
return checkedStamp;
|
||||
}
|
||||
|
||||
@NodeIntrinsic
|
||||
public static native boolean doInstanceof(@ConstantNodeParameter ResolvedJavaType type, Object object);
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ResolvedJavaType type, ValueNode object) {
|
||||
InstanceOfNode node = new InstanceOfNode(StampFactory.objectNonNull(TypeReference.create(b.getAssumptions(), type)), object, null, null);
|
||||
node = b.add(node);
|
||||
b.addPush(JavaKind.Int, ConditionalNode.create(node, NodeView.DEFAULT));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TriState implies(boolean thisNegated, LogicNode other) {
|
||||
if (other instanceof InstanceOfNode) {
|
||||
|
@ -32,6 +32,7 @@ import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.graph.NodeSourcePosition;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
@ -56,6 +57,11 @@ public class DelegatingReplacements implements Replacements {
|
||||
return delegate.getGraphBuilderPlugins();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends GraphBuilderPlugin> getIntrinsifyingPlugin(ResolvedJavaMethod method) {
|
||||
return delegate.getIntrinsifyingPlugin(method);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructuredGraph getSnippet(ResolvedJavaMethod method, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) {
|
||||
return delegate.getSnippet(method, args, trackNodeSourcePosition, replaceePosition);
|
||||
@ -67,8 +73,8 @@ public class DelegatingReplacements implements Replacements {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSnippet(ResolvedJavaMethod method, boolean trackNodeSourcePosition) {
|
||||
delegate.registerSnippet(method, trackNodeSourcePosition);
|
||||
public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) {
|
||||
delegate.registerSnippet(method, original, receiver, trackNodeSourcePosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -33,6 +33,7 @@ import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.graph.NodeSourcePosition;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
|
||||
@ -51,6 +52,11 @@ public interface Replacements {
|
||||
*/
|
||||
GraphBuilderConfiguration.Plugins getGraphBuilderPlugins();
|
||||
|
||||
/**
|
||||
* Gets the plugin type that intrinsifies calls to {@code method}.
|
||||
*/
|
||||
Class<? extends GraphBuilderPlugin> getIntrinsifyingPlugin(ResolvedJavaMethod method);
|
||||
|
||||
/**
|
||||
* Gets the snippet graph derived from a given method.
|
||||
*
|
||||
@ -75,7 +81,7 @@ public interface Replacements {
|
||||
/**
|
||||
* Registers a method as snippet.
|
||||
*/
|
||||
void registerSnippet(ResolvedJavaMethod method, boolean trackNodeSourcePosition);
|
||||
void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition);
|
||||
|
||||
/**
|
||||
* Gets a graph that is a substitution for a given method.
|
||||
@ -138,4 +144,13 @@ public interface Replacements {
|
||||
* {@link Replacements#registerSnippetTemplateCache(SnippetTemplateCache)}.
|
||||
*/
|
||||
<T extends SnippetTemplateCache> T getSnippetTemplateCache(Class<T> templatesClass);
|
||||
|
||||
/**
|
||||
* Notifies this method that no further snippets will be registered via {@link #registerSnippet}
|
||||
* or {@link #registerSnippetTemplateCache}.
|
||||
*
|
||||
* This is a hook for an implementation to check for or forbid late registration.
|
||||
*/
|
||||
default void closeSnippetRegistration() {
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2018, 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
|
||||
@ -22,32 +22,21 @@
|
||||
*/
|
||||
|
||||
|
||||
package org.graalvm.compiler.hotspot.replacements;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import sun.misc.Unsafe;
|
||||
package org.graalvm.compiler.options;
|
||||
|
||||
/**
|
||||
* Package private access to the {@link Unsafe} capability.
|
||||
* Used to suppress <a href="http://findbugs.sourceforge.net">FindBugs</a> warnings.
|
||||
*/
|
||||
class UnsafeAccess {
|
||||
public @interface SuppressFBWarnings {
|
||||
/**
|
||||
* The set of FindBugs
|
||||
* <a href="http://findbugs.sourceforge.net/bugDescriptions.html">warnings</a> that are to be
|
||||
* suppressed in annotated element. The value can be a bug category, kind or pattern.
|
||||
*/
|
||||
String[] value();
|
||||
|
||||
static final Unsafe UNSAFE = initUnsafe();
|
||||
|
||||
private static Unsafe initUnsafe() {
|
||||
try {
|
||||
// Fast path when we are trusted.
|
||||
return Unsafe.getUnsafe();
|
||||
} catch (SecurityException se) {
|
||||
// Slow path when we are not trusted.
|
||||
try {
|
||||
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
theUnsafe.setAccessible(true);
|
||||
return (Unsafe) theUnsafe.get(Unsafe.class);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("exception while trying to get Unsafe", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Reason why the warning is suppressed.
|
||||
*/
|
||||
String justification();
|
||||
}
|
@ -109,34 +109,42 @@ public class Providers implements CodeGenProviders {
|
||||
}
|
||||
|
||||
public Providers copyWith(MetaAccessProvider substitution) {
|
||||
assert this.getClass() == Providers.class : "must override";
|
||||
return new Providers(substitution, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider);
|
||||
}
|
||||
|
||||
public Providers copyWith(CodeCacheProvider substitution) {
|
||||
assert this.getClass() == Providers.class : "must override";
|
||||
return new Providers(metaAccess, substitution, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider);
|
||||
}
|
||||
|
||||
public Providers copyWith(ConstantReflectionProvider substitution) {
|
||||
assert this.getClass() == Providers.class : "must override";
|
||||
return new Providers(metaAccess, codeCache, substitution, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider);
|
||||
}
|
||||
|
||||
public Providers copyWith(ConstantFieldProvider substitution) {
|
||||
assert this.getClass() == Providers.class : "must override";
|
||||
return new Providers(metaAccess, codeCache, constantReflection, substitution, foreignCalls, lowerer, replacements, stampProvider);
|
||||
}
|
||||
|
||||
public Providers copyWith(ForeignCallsProvider substitution) {
|
||||
assert this.getClass() == Providers.class : "must override";
|
||||
return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, substitution, lowerer, replacements, stampProvider);
|
||||
}
|
||||
|
||||
public Providers copyWith(LoweringProvider substitution) {
|
||||
assert this.getClass() == Providers.class : "must override";
|
||||
return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, substitution, replacements, stampProvider);
|
||||
}
|
||||
|
||||
public Providers copyWith(Replacements substitution) {
|
||||
assert this.getClass() == Providers.class : "must override in " + getClass();
|
||||
return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, substitution, stampProvider);
|
||||
}
|
||||
|
||||
public Providers copyWith(StampProvider substitution) {
|
||||
assert this.getClass() == Providers.class : "must override";
|
||||
return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, substitution);
|
||||
}
|
||||
}
|
||||
|
@ -82,9 +82,12 @@ public class InjectedDependencies implements Iterable<Dependency> {
|
||||
public enum WellKnownDependency {
|
||||
CONSTANT_REFLECTION("b.getConstantReflection()", "jdk.vm.ci.meta.ConstantReflectionProvider"),
|
||||
META_ACCESS("b.getMetaAccess()", "jdk.vm.ci.meta.MetaAccessProvider"),
|
||||
ASSUMPTIONS("b.getAssumptions()", "jdk.vm.ci.meta.Assumptions"),
|
||||
OPTIONVALUES("b.getOptions()", "org.graalvm.compiler.options.OptionValues"),
|
||||
INJECTED_STAMP(new InjectedStampDependency()),
|
||||
SNIPPET_REFLECTION(new InjectedDependency("snippetReflection", "org.graalvm.compiler.api.replacements.SnippetReflectionProvider")),
|
||||
STAMP_PROVIDER("b.getStampProvider()", "org.graalvm.compiler.nodes.spi.StampProvider"),
|
||||
INTRINSIC_CONTEXT("b.getIntrinsic()", "org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext"),
|
||||
STRUCTURED_GRAPH("b.getGraph()", "org.graalvm.compiler.nodes.StructuredGraph");
|
||||
|
||||
private final String expr;
|
||||
|
@ -245,20 +245,29 @@ public final class NodeIntrinsicHandler extends AnnotationHandler {
|
||||
}
|
||||
|
||||
if (method.getParameters().size() < 2) {
|
||||
nonMatches.put(method, "Too few arguments");
|
||||
continue;
|
||||
}
|
||||
|
||||
VariableElement firstArg = method.getParameters().get(0);
|
||||
if (!isTypeCompatible(firstArg.asType(), processor.getType(GRAPH_BUILDER_CONTEXT_CLASS_NAME))) {
|
||||
nonMatches.put(method, "First argument isn't of type GraphBuilderContext");
|
||||
continue;
|
||||
}
|
||||
|
||||
VariableElement secondArg = method.getParameters().get(1);
|
||||
if (!isTypeCompatible(secondArg.asType(), processor.getType(RESOLVED_JAVA_METHOD_CLASS_NAME))) {
|
||||
nonMatches.put(method, "Second argument isn't of type ResolvedJavaMethod");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (method.getReturnType().getKind() != TypeKind.BOOLEAN) {
|
||||
nonMatches.put(method, "Doesn't return boolean");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!method.getModifiers().contains(Modifier.STATIC)) {
|
||||
nonMatches.put(method, "Method is non-static");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ public abstract class ReplacementsTest extends GraalCompilerTest {
|
||||
*/
|
||||
protected final ClassfileBytecodeProvider getSystemClassLoaderBytecodeProvider() {
|
||||
ReplacementsImpl d = (ReplacementsImpl) getReplacements();
|
||||
MetaAccessProvider metaAccess = d.providers.getMetaAccess();
|
||||
MetaAccessProvider metaAccess = d.getProviders().getMetaAccess();
|
||||
ClassfileBytecodeProvider bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, d.snippetReflection, ClassLoader.getSystemClassLoader());
|
||||
return bytecodeProvider;
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ public abstract class SnippetsTest extends ReplacementsTest {
|
||||
protected SnippetsTest() {
|
||||
ReplacementsImpl d = (ReplacementsImpl) getReplacements();
|
||||
bytecodeProvider = getSystemClassLoaderBytecodeProvider();
|
||||
installer = new ReplacementsImpl(getInitialOptions(), null, d.providers, d.snippetReflection, bytecodeProvider, d.target);
|
||||
installer = new ReplacementsImpl(getInitialOptions(), null, d.getProviders(), d.snippetReflection, bytecodeProvider, d.target);
|
||||
installer.setGraphBuilderPlugins(d.getGraphBuilderPlugins());
|
||||
}
|
||||
|
||||
|
@ -93,6 +93,7 @@ public class StringCompareToTest extends StringSubstitutionTestBase {
|
||||
needCheckNode = false;
|
||||
} else {
|
||||
List<String> vmArgs = GraalServices.getInputArguments();
|
||||
Assume.assumeTrue(vmArgs != null);
|
||||
for (String vmArg : vmArgs) {
|
||||
if (vmArg.equals(DISABLE_COMPACTSTRINGS_FLAG)) {
|
||||
needCheckNode = false;
|
||||
|
@ -83,6 +83,7 @@ import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.JavaType;
|
||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
import jdk.vm.ci.meta.Signature;
|
||||
|
||||
/**
|
||||
@ -218,11 +219,12 @@ public class GraphKit implements GraphBuilderTool {
|
||||
}
|
||||
|
||||
public ResolvedJavaMethod findMethod(Class<?> declaringClass, String name, boolean isStatic) {
|
||||
ResolvedJavaType type = providers.getMetaAccess().lookupJavaType(declaringClass);
|
||||
ResolvedJavaMethod method = null;
|
||||
for (Method m : declaringClass.getDeclaredMethods()) {
|
||||
for (ResolvedJavaMethod m : type.getDeclaredMethods()) {
|
||||
if (Modifier.isStatic(m.getModifiers()) == isStatic && m.getName().equals(name)) {
|
||||
assert method == null : "found more than one method in " + declaringClass + " named " + name;
|
||||
method = providers.getMetaAccess().lookupJavaMethod(m);
|
||||
method = m;
|
||||
}
|
||||
}
|
||||
GraalError.guarantee(method != null, "Could not find %s.%s (%s)", declaringClass, name, isStatic ? "static" : "non-static");
|
||||
@ -356,7 +358,8 @@ public class GraphKit implements GraphBuilderTool {
|
||||
Plugins plugins = new Plugins(graphBuilderPlugins);
|
||||
GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins);
|
||||
|
||||
StructuredGraph calleeGraph = new StructuredGraph.Builder(invoke.getOptions(), invoke.getDebug()).method(method).trackNodeSourcePosition(invoke.graph().trackNodeSourcePosition()).build();
|
||||
StructuredGraph calleeGraph = new StructuredGraph.Builder(invoke.getOptions(), invoke.getDebug()).method(method).trackNodeSourcePosition(
|
||||
invoke.graph().trackNodeSourcePosition()).setIsSubstitution(true).build();
|
||||
IntrinsicContext initialReplacementContext = new IntrinsicContext(method, method, providers.getReplacements().getDefaultReplacementBytecodeProvider(), INLINE_AFTER_PARSING);
|
||||
GraphBuilderPhase.Instance instance = createGraphBuilderInstance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), providers.getConstantFieldProvider(), config,
|
||||
OptimisticOptimizations.NONE,
|
||||
|
@ -76,6 +76,8 @@ public class NodeIntrinsificationProvider implements InjectionProvider {
|
||||
return type.cast(foreignCalls);
|
||||
} else if (type.equals(SnippetReflectionProvider.class)) {
|
||||
return type.cast(snippetReflection);
|
||||
} else if (type.equals(WordTypes.class)) {
|
||||
return type.cast(wordTypes);
|
||||
} else {
|
||||
throw new GraalError("Cannot handle injected argument of type %s.", type.getName());
|
||||
}
|
||||
|
@ -419,10 +419,18 @@ public abstract class PEGraphDecoder extends SimplifyingGraphDecoder {
|
||||
protected FixedWithNextNode lastInstr;
|
||||
protected ValueNode pushedNode;
|
||||
protected boolean invokeConsumed;
|
||||
protected final InvokeKind invokeKind;
|
||||
protected final JavaType invokeReturnType;
|
||||
|
||||
public PEAppendGraphBuilderContext(PEMethodScope inlineScope, FixedWithNextNode lastInstr) {
|
||||
this(inlineScope, lastInstr, null, null);
|
||||
}
|
||||
|
||||
public PEAppendGraphBuilderContext(PEMethodScope inlineScope, FixedWithNextNode lastInstr, InvokeKind invokeKind, JavaType invokeReturnType) {
|
||||
super(inlineScope, inlineScope.invokeData != null ? inlineScope.invokeData.invoke : null);
|
||||
this.lastInstr = lastInstr;
|
||||
this.invokeKind = invokeKind;
|
||||
this.invokeReturnType = invokeReturnType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -482,6 +490,22 @@ public abstract class PEGraphDecoder extends SimplifyingGraphDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InvokeKind getInvokeKind() {
|
||||
if (invokeKind != null) {
|
||||
return invokeKind;
|
||||
}
|
||||
return super.getInvokeKind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getInvokeReturnType() {
|
||||
if (invokeReturnType != null) {
|
||||
return invokeReturnType;
|
||||
}
|
||||
return super.getInvokeReturnType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleReplacedInvoke(CallTargetNode callTarget, JavaKind resultType) {
|
||||
if (invokeConsumed) {
|
||||
@ -727,7 +751,9 @@ public abstract class PEGraphDecoder extends SimplifyingGraphDecoder {
|
||||
invoke.asNode().replaceAtPredecessor(null);
|
||||
|
||||
PEMethodScope inlineScope = new PEMethodScope(graph, methodScope, loopScope, null, targetMethod, invokeData, methodScope.inliningDepth + 1, loopExplosionPlugin, arguments);
|
||||
PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(inlineScope, invokePredecessor);
|
||||
|
||||
JavaType returnType = targetMethod.getSignature().getReturnType(methodScope.method.getDeclaringClass());
|
||||
PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(inlineScope, invokePredecessor, callTarget.invokeKind(), returnType);
|
||||
InvocationPluginReceiver invocationPluginReceiver = new InvocationPluginReceiver(graphBuilderContext);
|
||||
|
||||
if (invocationPlugin.execute(graphBuilderContext, targetMethod, invocationPluginReceiver.init(targetMethod, arguments), arguments)) {
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
package org.graalvm.compiler.replacements;
|
||||
|
||||
import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
|
||||
import static org.graalvm.compiler.core.common.GraalOptions.UseSnippetGraphCache;
|
||||
import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM;
|
||||
import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing;
|
||||
@ -72,6 +73,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedInvocationPlugin;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
|
||||
@ -98,7 +100,16 @@ import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
public class ReplacementsImpl implements Replacements, InlineInvokePlugin {
|
||||
|
||||
protected final OptionValues options;
|
||||
public final Providers providers;
|
||||
|
||||
public Providers getProviders() {
|
||||
return providers;
|
||||
}
|
||||
|
||||
public void setProviders(Providers providers) {
|
||||
this.providers = providers.copyWith(this);
|
||||
}
|
||||
|
||||
protected Providers providers;
|
||||
public final SnippetReflectionProvider snippetReflection;
|
||||
public final TargetDescription target;
|
||||
private GraphBuilderConfiguration.Plugins graphBuilderPlugins;
|
||||
@ -130,12 +141,15 @@ public class ReplacementsImpl implements Replacements, InlineInvokePlugin {
|
||||
return graphBuilderPlugins;
|
||||
}
|
||||
|
||||
protected boolean hasGeneratedInvocationPluginAnnotation(ResolvedJavaMethod method) {
|
||||
return method.getAnnotation(Node.NodeIntrinsic.class) != null || method.getAnnotation(Fold.class) != null;
|
||||
}
|
||||
|
||||
protected boolean hasGenericInvocationPluginAnnotation(ResolvedJavaMethod method) {
|
||||
return method.getAnnotation(Word.Operation.class) != null;
|
||||
@Override
|
||||
public Class<? extends GraphBuilderPlugin> getIntrinsifyingPlugin(ResolvedJavaMethod method) {
|
||||
if (method.getAnnotation(Node.NodeIntrinsic.class) != null || method.getAnnotation(Fold.class) != null) {
|
||||
return GeneratedInvocationPlugin.class;
|
||||
}
|
||||
if (method.getAnnotation(Word.Operation.class) != null) {
|
||||
return WordOperationPlugin.class;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final int MAX_GRAPH_INLINING_DEPTH = 100; // more than enough
|
||||
@ -163,7 +177,8 @@ public class ReplacementsImpl implements Replacements, InlineInvokePlugin {
|
||||
// Force inlining when parsing replacements
|
||||
return createIntrinsicInlineInfo(method, null, defaultBytecodeProvider);
|
||||
} else {
|
||||
assert method.getAnnotation(NodeIntrinsic.class) == null : String.format("@%s method %s must only be called from within a replacement%n%s", NodeIntrinsic.class.getSimpleName(),
|
||||
assert IS_BUILDING_NATIVE_IMAGE || method.getAnnotation(NodeIntrinsic.class) == null : String.format("@%s method %s must only be called from within a replacement%n%s",
|
||||
NodeIntrinsic.class.getSimpleName(),
|
||||
method.format("%h.%n"), b);
|
||||
}
|
||||
return null;
|
||||
@ -174,13 +189,15 @@ public class ReplacementsImpl implements Replacements, InlineInvokePlugin {
|
||||
if (b.parsingIntrinsic()) {
|
||||
IntrinsicContext intrinsic = b.getIntrinsic();
|
||||
if (!intrinsic.isCallToOriginal(method)) {
|
||||
if (hasGeneratedInvocationPluginAnnotation(method)) {
|
||||
throw new GraalError("%s should have been handled by a %s", method.format("%H.%n(%p)"), GeneratedInvocationPlugin.class.getSimpleName());
|
||||
Class<? extends GraphBuilderPlugin> pluginClass = getIntrinsifyingPlugin(method);
|
||||
if (pluginClass != null) {
|
||||
String methodDesc = method.format("%H.%n(%p)");
|
||||
throw new GraalError("Call to %s should have been intrinsified by a %s. " +
|
||||
"This is typically caused by Eclipse failing to run an annotation " +
|
||||
"processor. This can usually be fixed by forcing Eclipse to rebuild " +
|
||||
"the source file in which %s is declared",
|
||||
methodDesc, pluginClass.getSimpleName(), methodDesc);
|
||||
}
|
||||
if (hasGenericInvocationPluginAnnotation(method)) {
|
||||
throw new GraalError("%s should have been handled by %s", method.format("%H.%n(%p)"), WordOperationPlugin.class.getSimpleName());
|
||||
}
|
||||
|
||||
throw new GraalError("All non-recursive calls in the intrinsic %s must be inlined or intrinsified: found call to %s",
|
||||
intrinsic.getIntrinsicMethod().format("%H.%n(%p)"), method.format("%h.%n(%p)"));
|
||||
}
|
||||
@ -213,7 +230,7 @@ public class ReplacementsImpl implements Replacements, InlineInvokePlugin {
|
||||
|
||||
private static final AtomicInteger nextDebugContextId = new AtomicInteger();
|
||||
|
||||
protected DebugContext openDebugContext(String idPrefix, ResolvedJavaMethod method) {
|
||||
public DebugContext openDebugContext(String idPrefix, ResolvedJavaMethod method) {
|
||||
DebugContext outer = DebugContext.forCurrentThread();
|
||||
Description description = new Description(method, idPrefix + nextDebugContextId.incrementAndGet());
|
||||
List<DebugHandlersFactory> factories = debugHandlersFactory == null ? Collections.emptyList() : Collections.singletonList(debugHandlersFactory);
|
||||
@ -249,7 +266,7 @@ public class ReplacementsImpl implements Replacements, InlineInvokePlugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSnippet(ResolvedJavaMethod method, boolean trackNodeSourcePosition) {
|
||||
public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) {
|
||||
// No initialization needed as snippet graphs are created on demand in getSnippet
|
||||
}
|
||||
|
||||
@ -386,7 +403,7 @@ public class ReplacementsImpl implements Replacements, InlineInvokePlugin {
|
||||
*/
|
||||
protected final ResolvedJavaMethod substitutedMethod;
|
||||
|
||||
protected GraphMaker(ReplacementsImpl replacements, ResolvedJavaMethod substitute, ResolvedJavaMethod substitutedMethod) {
|
||||
public GraphMaker(ReplacementsImpl replacements, ResolvedJavaMethod substitute, ResolvedJavaMethod substitutedMethod) {
|
||||
this.replacements = replacements;
|
||||
this.method = substitute;
|
||||
this.substitutedMethod = substitutedMethod;
|
||||
@ -488,13 +505,15 @@ public class ReplacementsImpl implements Replacements, InlineInvokePlugin {
|
||||
|
||||
IntrinsicContext initialIntrinsicContext = null;
|
||||
Snippet snippetAnnotation = method.getAnnotation(Snippet.class);
|
||||
if (snippetAnnotation == null) {
|
||||
MethodSubstitution methodAnnotation = method.getAnnotation(MethodSubstitution.class);
|
||||
if (methodAnnotation == null && snippetAnnotation == null) {
|
||||
// Post-parse inlined intrinsic
|
||||
initialIntrinsicContext = new IntrinsicContext(substitutedMethod, method, bytecodeProvider, INLINE_AFTER_PARSING);
|
||||
} else {
|
||||
// Snippet
|
||||
ResolvedJavaMethod original = substitutedMethod != null ? substitutedMethod : method;
|
||||
initialIntrinsicContext = new IntrinsicContext(original, method, bytecodeProvider, INLINE_AFTER_PARSING, snippetAnnotation.allowPartialIntrinsicArgumentMismatch());
|
||||
initialIntrinsicContext = new IntrinsicContext(original, method, bytecodeProvider, INLINE_AFTER_PARSING,
|
||||
snippetAnnotation != null ? snippetAnnotation.allowPartialIntrinsicArgumentMismatch() : true);
|
||||
}
|
||||
|
||||
createGraphBuilder(metaAccess, replacements.providers.getStampProvider(), replacements.providers.getConstantReflection(), replacements.providers.getConstantFieldProvider(), config,
|
||||
|
@ -51,6 +51,18 @@ public final class ReplacementsUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static void staticAssert(boolean condition, String message, Object arg1) {
|
||||
if (REPLACEMENTS_ASSERTIONS_ENABLED) {
|
||||
AssertionNode.assertion(true, condition, message, arg1, "");
|
||||
}
|
||||
}
|
||||
|
||||
public static void staticAssert(boolean condition, String message, Object arg1, Object arg2) {
|
||||
if (REPLACEMENTS_ASSERTIONS_ENABLED) {
|
||||
AssertionNode.assertion(true, condition, message, arg1, arg2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that condition evaluates to true at runtime. This is intended to be used within
|
||||
* snippets or stubs, and will lead to a VM error if it fails.
|
||||
|
@ -64,6 +64,7 @@ import org.graalvm.compiler.core.common.type.Stamp;
|
||||
import org.graalvm.compiler.core.common.type.StampFactory;
|
||||
import org.graalvm.compiler.core.common.type.StampPair;
|
||||
import org.graalvm.compiler.core.common.type.TypeReference;
|
||||
import org.graalvm.compiler.debug.Assertions;
|
||||
import org.graalvm.compiler.debug.CounterKey;
|
||||
import org.graalvm.compiler.debug.DebugCloseable;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
@ -170,7 +171,7 @@ public class SnippetTemplate {
|
||||
public abstract static class SnippetInfo {
|
||||
|
||||
protected final ResolvedJavaMethod method;
|
||||
protected ResolvedJavaMethod original;
|
||||
protected final ResolvedJavaMethod original;
|
||||
protected final LocationIdentity[] privateLocations;
|
||||
protected final Object receiver;
|
||||
|
||||
@ -269,8 +270,9 @@ public class SnippetTemplate {
|
||||
|
||||
protected abstract Lazy lazy();
|
||||
|
||||
protected SnippetInfo(ResolvedJavaMethod method, LocationIdentity[] privateLocations, Object receiver) {
|
||||
protected SnippetInfo(ResolvedJavaMethod method, ResolvedJavaMethod original, LocationIdentity[] privateLocations, Object receiver) {
|
||||
this.method = method;
|
||||
this.original = original;
|
||||
this.privateLocations = privateLocations;
|
||||
instantiationCounter = DebugContext.counter("SnippetInstantiationCount[%s]", method.getName());
|
||||
instantiationTimer = DebugContext.timer("SnippetInstantiationTime[%s]", method.getName());
|
||||
@ -285,10 +287,6 @@ public class SnippetTemplate {
|
||||
return lazy().constantParameters.length;
|
||||
}
|
||||
|
||||
public void setOriginalMethod(ResolvedJavaMethod original) {
|
||||
this.original = original;
|
||||
}
|
||||
|
||||
public boolean isConstantParameter(int paramIdx) {
|
||||
return lazy().constantParameters[paramIdx];
|
||||
}
|
||||
@ -318,8 +316,8 @@ public class SnippetTemplate {
|
||||
protected static class LazySnippetInfo extends SnippetInfo {
|
||||
protected final AtomicReference<Lazy> lazy = new AtomicReference<>(null);
|
||||
|
||||
protected LazySnippetInfo(ResolvedJavaMethod method, LocationIdentity[] privateLocations, Object receiver) {
|
||||
super(method, privateLocations, receiver);
|
||||
protected LazySnippetInfo(ResolvedJavaMethod method, ResolvedJavaMethod original, LocationIdentity[] privateLocations, Object receiver) {
|
||||
super(method, original, privateLocations, receiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -334,8 +332,8 @@ public class SnippetTemplate {
|
||||
protected static class EagerSnippetInfo extends SnippetInfo {
|
||||
protected final Lazy lazy;
|
||||
|
||||
protected EagerSnippetInfo(ResolvedJavaMethod method, LocationIdentity[] privateLocations, Object receiver) {
|
||||
super(method, privateLocations, receiver);
|
||||
protected EagerSnippetInfo(ResolvedJavaMethod method, ResolvedJavaMethod original, LocationIdentity[] privateLocations, Object receiver) {
|
||||
super(method, original, privateLocations, receiver);
|
||||
lazy = new Lazy(method);
|
||||
}
|
||||
|
||||
@ -642,28 +640,45 @@ public class SnippetTemplate {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ResolvedJavaMethod findMethod(MetaAccessProvider metaAccess, Class<?> declaringClass, String methodName) {
|
||||
ResolvedJavaType type = metaAccess.lookupJavaType(declaringClass);
|
||||
ResolvedJavaMethod result = null;
|
||||
for (ResolvedJavaMethod m : type.getDeclaredMethods()) {
|
||||
if (m.getName().equals(methodName)) {
|
||||
if (!Assertions.assertionsEnabled()) {
|
||||
return m;
|
||||
} else {
|
||||
assert result == null : "multiple definitions found";
|
||||
result = m;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result == null) {
|
||||
throw new GraalError("Could not find method in " + declaringClass + " named " + methodName);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected SnippetInfo snippet(Class<? extends Snippets> declaringClass, String methodName, LocationIdentity... initialPrivateLocations) {
|
||||
return snippet(declaringClass, methodName, null, initialPrivateLocations);
|
||||
return snippet(declaringClass, methodName, null, null, initialPrivateLocations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the unique method in {@code declaringClass} named {@code methodName} annotated by
|
||||
* {@link Snippet} and returns a {@link SnippetInfo} value describing it. There must be
|
||||
* exactly one snippet method in {@code declaringClass}.
|
||||
* exactly one snippet method in {@code declaringClass} with a given name.
|
||||
*/
|
||||
protected SnippetInfo snippet(Class<? extends Snippets> declaringClass, String methodName, Object receiver, LocationIdentity... initialPrivateLocations) {
|
||||
protected SnippetInfo snippet(Class<? extends Snippets> declaringClass, String methodName, ResolvedJavaMethod original, Object receiver, LocationIdentity... initialPrivateLocations) {
|
||||
assert methodName != null;
|
||||
Method method = findMethod(declaringClass, methodName, null);
|
||||
assert method != null : "did not find @" + Snippet.class.getSimpleName() + " method in " + declaringClass + " named " + methodName;
|
||||
assert method.getAnnotation(Snippet.class) != null : method + " must be annotated with @" + Snippet.class.getSimpleName();
|
||||
assert findMethod(declaringClass, methodName, method) == null : "found more than one method named " + methodName + " in " + declaringClass;
|
||||
ResolvedJavaMethod javaMethod = providers.getMetaAccess().lookupJavaMethod(method);
|
||||
providers.getReplacements().registerSnippet(javaMethod, GraalOptions.TrackNodeSourcePosition.getValue(options));
|
||||
ResolvedJavaMethod javaMethod = findMethod(providers.getMetaAccess(), declaringClass, methodName);
|
||||
assert javaMethod != null : "did not find @" + Snippet.class.getSimpleName() + " method in " + declaringClass + " named " + methodName;
|
||||
assert javaMethod.getAnnotation(Snippet.class) != null : javaMethod + " must be annotated with @" + Snippet.class.getSimpleName();
|
||||
providers.getReplacements().registerSnippet(javaMethod, original, receiver, GraalOptions.TrackNodeSourcePosition.getValue(options));
|
||||
LocationIdentity[] privateLocations = GraalOptions.SnippetCounters.getValue(options) ? SnippetCounterNode.addSnippetCounters(initialPrivateLocations) : initialPrivateLocations;
|
||||
if (GraalOptions.EagerSnippets.getValue(options)) {
|
||||
return new EagerSnippetInfo(javaMethod, privateLocations, receiver);
|
||||
return new EagerSnippetInfo(javaMethod, original, privateLocations, receiver);
|
||||
} else {
|
||||
return new LazySnippetInfo(javaMethod, privateLocations, receiver);
|
||||
return new LazySnippetInfo(javaMethod, original, privateLocations, receiver);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1038,7 +1053,7 @@ public class SnippetTemplate {
|
||||
LoopEx loop = new LoopsData(snippetCopy).loop(loopBegin);
|
||||
Mark mark = snippetCopy.getMark();
|
||||
LoopTransformations.fullUnroll(loop, phaseContext, new CanonicalizerPhase());
|
||||
new CanonicalizerPhase().applyIncremental(snippetCopy, phaseContext, mark);
|
||||
new CanonicalizerPhase().applyIncremental(snippetCopy, phaseContext, mark, false);
|
||||
loop.deleteUnusedNodes();
|
||||
}
|
||||
GraphUtil.removeFixedWithUnusedInputs(explodeLoop);
|
||||
|
@ -30,7 +30,6 @@ import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQ
|
||||
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY;
|
||||
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.EnumMap;
|
||||
|
||||
import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
|
||||
@ -290,7 +289,7 @@ public abstract class ArrayCopySnippets implements Snippets {
|
||||
DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
|
||||
}
|
||||
} else {
|
||||
ReplacementsUtil.staticAssert(false, "unknown array type check");
|
||||
ReplacementsUtil.staticAssert(false, "unknown array type check ", arrayTypeCheck);
|
||||
}
|
||||
}
|
||||
|
||||
@ -384,8 +383,7 @@ public abstract class ArrayCopySnippets implements Snippets {
|
||||
}
|
||||
|
||||
protected SnippetInfo snippet(ArrayCopySnippets receiver, String methodName) {
|
||||
SnippetInfo info = snippet(ArrayCopySnippets.class, methodName, receiver, LocationIdentity.any());
|
||||
info.setOriginalMethod(originalArraycopy());
|
||||
SnippetInfo info = snippet(ArrayCopySnippets.class, methodName, originalArraycopy(), receiver, LocationIdentity.any());
|
||||
return info;
|
||||
}
|
||||
|
||||
@ -577,13 +575,11 @@ public abstract class ArrayCopySnippets implements Snippets {
|
||||
|
||||
private ResolvedJavaMethod originalArraycopy() throws GraalError {
|
||||
if (originalArraycopy == null) {
|
||||
Method method;
|
||||
try {
|
||||
method = System.class.getDeclaredMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class);
|
||||
} catch (NoSuchMethodException | SecurityException e) {
|
||||
originalArraycopy = findMethod(providers.getMetaAccess(), System.class, "arraycopy");
|
||||
} catch (SecurityException e) {
|
||||
throw new GraalError(e);
|
||||
}
|
||||
originalArraycopy = providers.getMetaAccess().lookupJavaMethod(method);
|
||||
}
|
||||
return originalArraycopy;
|
||||
}
|
||||
|
@ -56,11 +56,11 @@ public final class AssertionNode extends FixedWithNextNode implements Lowerable,
|
||||
protected final boolean compileTimeAssertion;
|
||||
protected final String message;
|
||||
|
||||
public AssertionNode(boolean compileTimeAssertion, ValueNode condition, String message) {
|
||||
public AssertionNode(boolean compileTimeAssertion, ValueNode condition, String message, Object arg1, Object arg2) {
|
||||
super(TYPE, StampFactory.forVoid());
|
||||
this.condition = condition;
|
||||
this.compileTimeAssertion = compileTimeAssertion;
|
||||
this.message = message;
|
||||
this.message = message + arg1 + arg2;
|
||||
}
|
||||
|
||||
public ValueNode condition() {
|
||||
@ -112,5 +112,14 @@ public final class AssertionNode extends FixedWithNextNode implements Lowerable,
|
||||
}
|
||||
|
||||
@NodeIntrinsic
|
||||
public static native void assertion(@ConstantNodeParameter boolean compileTimeAssertion, boolean condition, @ConstantNodeParameter String message);
|
||||
public static native void assertion(@ConstantNodeParameter boolean compileTimeAssertion, boolean condition, @ConstantNodeParameter String message, @ConstantNodeParameter Object arg1,
|
||||
@ConstantNodeParameter Object arg2);
|
||||
|
||||
public static void assertion(@ConstantNodeParameter boolean compileTimeAssertion, boolean condition, @ConstantNodeParameter String message) {
|
||||
assertion(compileTimeAssertion, condition, message, "", "");
|
||||
}
|
||||
|
||||
public static void assertion(@ConstantNodeParameter boolean compileTimeAssertion, boolean condition, @ConstantNodeParameter String message, @ConstantNodeParameter Object arg1) {
|
||||
assertion(compileTimeAssertion, condition, message, arg1, "");
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ done
|
||||
|
||||
$JAVA_HOME/bin/javac -d . $DIR/$TEST.java
|
||||
|
||||
JAOTC_OPTS="-J-Xmx4g --compile-for-tiered --info"
|
||||
JAOTC_OPTS="-J-ea -J-Xmx4g --compile-for-tiered --info"
|
||||
JAVA_OPTS="-Xmx4g -XX:+UseAOT -XX:+UnlockDiagnosticVMOptions -XX:+UseAOTStrictLoading"
|
||||
|
||||
# Compile with: +UseCompressedOops +UseG1GC
|
||||
|
Loading…
x
Reference in New Issue
Block a user