8215224: Update Graal

Reviewed-by: kvn
This commit is contained in:
Igor Veresov 2018-12-11 16:50:43 -08:00
parent 13b56530f4
commit 8d8b784c9e
69 changed files with 1016 additions and 648 deletions

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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]);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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",

View File

@ -55,6 +55,11 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest {
public int hashCode() {
return clazz.hashCode();
}
@Override
public String toString() {
return "Wrapper-" + clazz;
}
}
@Override

View File

@ -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);

View File

@ -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();

View File

@ -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();

View File

@ -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;
}

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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);
}

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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") {

View File

@ -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);

View File

@ -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);

View File

@ -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();

View File

@ -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"));
}
}

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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.

View File

@ -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;
}
}

View File

@ -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());

View File

@ -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;
}
}

View File

@ -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}.
*

View File

@ -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);
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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) {

View File

@ -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

View File

@ -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() {
}
}

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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());
}

View File

@ -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;

View File

@ -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,

View File

@ -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());
}

View File

@ -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)) {

View File

@ -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,

View File

@ -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.

View File

@ -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);

View File

@ -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;
}

View File

@ -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, "");
}
}

View File

@ -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