# HG changeset patch # User Doug Simon # Date 1424341364 -3600 # Node ID b828f1f7462512f8abdc05c6841e8da710e48f90 # Parent 787a3c7235ef0be26d5cb3c9318f2f7db78c67a4 add graph builder plugins for Unsafe and Word diff -r 787a3c7235ef -r b828f1f74625 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java Thu Feb 19 11:21:40 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java Thu Feb 19 11:22:44 2015 +0100 @@ -33,6 +33,7 @@ import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.replacements.*; /** * Common functionality of HotSpot host backends. @@ -73,7 +74,7 @@ try (InitTimer st = timer("graphBuilderPlugins.initialize")) { GraphBuilderPhase phase = (GraphBuilderPhase) providers.getSuites().getDefaultGraphBuilderSuite().findPhase(GraphBuilderPhase.class).previous(); InvocationPlugins plugins = phase.getGraphBuilderConfig().getInvocationPlugins(); - registerInvocationPlugins(providers.getMetaAccess(), plugins); + registerInvocationPlugins(providers, plugins); } try (InitTimer st = timer("foreignCalls.initialize")) { @@ -105,8 +106,8 @@ } } - protected void registerInvocationPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { - StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, plugins); - HotSpotGraphBuilderPlugins.registerInvocationPlugins(metaAccess, plugins); + protected void registerInvocationPlugins(HotSpotProviders providers, InvocationPlugins plugins) { + StandardGraphBuilderPlugins.registerInvocationPlugins(providers.getMetaAccess(), plugins); + HotSpotGraphBuilderPlugins.registerInvocationPlugins(providers, plugins); } } diff -r 787a3c7235ef -r b828f1f74625 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java Thu Feb 19 11:21:40 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java Thu Feb 19 11:22:44 2015 +0100 @@ -22,27 +22,39 @@ */ package com.oracle.graal.hotspot.meta; +import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.java.GraphBuilderContext.*; +import static java.lang.Character.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.hotspot.word.*; import com.oracle.graal.java.*; import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin; import com.oracle.graal.java.InvocationPlugins.Registration; import com.oracle.graal.java.InvocationPlugins.Registration.Receiver; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.options.*; +import com.oracle.graal.word.*; +import com.oracle.graal.word.nodes.*; /** * Provides HotSpot specific {@link InvocationPlugin}s. */ public class HotSpotGraphBuilderPlugins { - public static void registerInvocationPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + public static void registerInvocationPlugins(HotSpotProviders providers, InvocationPlugins plugins) { + MetaAccessProvider metaAccess = providers.getMetaAccess(); + SnippetReflectionProvider snippetReflection = providers.getSnippetReflection(); + Kind wordKind = providers.getCodeCache().getTarget().wordKind; + // Object.class Registration r = new Registration(plugins, metaAccess, Object.class); r.register1("getClass", Receiver.class, new InvocationPlugin() { @@ -103,5 +115,130 @@ return false; } }); + + // MetaspacePointer.class + r = new Registration(plugins, metaAccess, MetaspacePointer.class); + r.register1("isNull", Receiver.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode pointer) { + assert pointer.stamp() instanceof MetaspacePointerStamp; + IsNullNode isNull = builder.append(new IsNullNode(pointer)); + ConstantNode trueValue = builder.append(ConstantNode.forBoolean(true)); + ConstantNode falseValue = builder.append(ConstantNode.forBoolean(false)); + builder.push(Kind.Boolean.getStackKind(), builder.append(new ConditionalNode(isNull, trueValue, falseValue))); + return true; + } + }); + r.register1("asWord", Receiver.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode pointer) { + builder.append(new PointerCastNode(StampFactory.forKind(wordKind), pointer)); + return true; + } + }); + r.register2("readObject", Receiver.class, int.class, new ReadOp(snippetReflection, wordKind, Kind.Object, BarrierType.NONE, true)); + r.register3("readObject", Receiver.class, int.class, LocationIdentity.class, new ReadOp(snippetReflection, wordKind, Kind.Object, BarrierType.NONE, true)); + r.register3("readObject", Receiver.class, int.class, BarrierType.class, new ReadOp(snippetReflection, wordKind, Kind.Object, BarrierType.NONE, true)); + r.register2("readObject", Receiver.class, WordBase.class, new ReadOp(snippetReflection, wordKind, Kind.Object, BarrierType.NONE, true)); + r.register3("readObject", Receiver.class, WordBase.class, LocationIdentity.class, new ReadOp(snippetReflection, wordKind, Kind.Object, BarrierType.NONE, true)); + r.register3("readObject", Receiver.class, WordBase.class, BarrierType.class, new ReadOp(snippetReflection, wordKind, Kind.Object, BarrierType.NONE, true)); + + registerWordOpPlugins(r, snippetReflection, wordKind, Kind.Byte, Kind.Short, Kind.Char, Kind.Int, Kind.Float, Kind.Long, Kind.Double); + } + + protected static void registerWordOpPlugins(Registration r, SnippetReflectionProvider snippetReflection, Kind wordKind, Kind... kinds) { + for (Kind kind : kinds) { + String kindName = kind.getJavaName(); + kindName = toUpperCase(kindName.charAt(0)) + kindName.substring(1); + String getName = "read" + kindName; + // String putName = "write" + kindName; + r.register2(getName, Receiver.class, int.class, new ReadOp(snippetReflection, wordKind, kind)); + r.register3(getName, Receiver.class, int.class, LocationIdentity.class, new ReadOp(snippetReflection, wordKind, kind)); + } + } + + static class ReadOp implements InvocationPlugin { + final SnippetReflectionProvider snippetReflection; + final Kind wordKind; + final Kind resultKind; + final BarrierType barrierType; + final boolean compressible; + + public ReadOp(SnippetReflectionProvider snippetReflection, Kind wordKind, Kind resultKind, BarrierType barrierType, boolean compressible) { + this.snippetReflection = snippetReflection; + this.wordKind = wordKind; + this.resultKind = resultKind; + this.barrierType = barrierType; + this.compressible = compressible; + } + + public ReadOp(SnippetReflectionProvider snippetReflection, Kind wordKind, Kind resultKind) { + this(snippetReflection, wordKind, resultKind, BarrierType.NONE, false); + } + + public boolean apply(GraphBuilderContext builder, ValueNode pointer, ValueNode offset) { + LocationNode location = makeLocation(builder, offset, ANY_LOCATION, wordKind); + builder.push(resultKind, builder.append(readOp(builder, resultKind, pointer, location, barrierType, compressible))); + return true; + } + + public boolean apply(GraphBuilderContext builder, ValueNode pointer, ValueNode offset, ValueNode locationIdentityArg) { + assert locationIdentityArg.isConstant(); + LocationIdentity locationIdentity = snippetReflection.asObject(LocationIdentity.class, locationIdentityArg.asJavaConstant()); + LocationNode location = makeLocation(builder, offset, locationIdentity, wordKind); + builder.push(resultKind, builder.append(readOp(builder, resultKind, pointer, location, barrierType, compressible))); + return true; + } + } + + public static ValueNode readOp(GraphBuilderContext builder, Kind readKind, ValueNode base, LocationNode location, BarrierType barrierType, boolean compressible) { + JavaReadNode read = builder.append(new JavaReadNode(readKind, base, location, barrierType, compressible)); + /* + * The read must not float outside its block otherwise it may float above an explicit zero + * check on its base address. + */ + read.setGuard(builder.getCurrentBlockGuard()); + return read; + } + + public static LocationNode makeLocation(GraphBuilderContext builder, ValueNode offset, LocationIdentity locationIdentity, Kind wordKind) { + return builder.append(new IndexedLocationNode(locationIdentity, 0, fromSigned(builder, offset, wordKind), 1)); + } + + public static LocationNode makeLocation(GraphBuilderContext builder, ValueNode offset, ValueNode locationIdentity, Kind wordKind) { + if (locationIdentity.isConstant()) { + return makeLocation(builder, offset, builder.getSnippetReflection().asObject(LocationIdentity.class, locationIdentity.asJavaConstant()), wordKind); + } + return builder.append(new SnippetLocationNode(builder.getSnippetReflection(), locationIdentity, builder.append(ConstantNode.forLong(0)), fromSigned(builder, offset, wordKind), + builder.append(ConstantNode.forInt(1)))); + } + + public static ValueNode fromUnsigned(GraphBuilderContext builder, ValueNode value, Kind wordKind) { + return convert(builder, value, wordKind, true); + } + + public static ValueNode fromSigned(GraphBuilderContext builder, ValueNode value, Kind wordKind) { + return convert(builder, value, wordKind, false); + } + + public static ValueNode toUnsigned(GraphBuilderContext builder, ValueNode value, Kind toKind) { + return convert(builder, value, toKind, true); + } + + public static ValueNode convert(GraphBuilderContext builder, ValueNode value, Kind toKind, boolean unsigned) { + if (value.getKind() == toKind) { + return value; + } + + if (toKind == Kind.Int) { + assert value.getKind() == Kind.Long; + return builder.append(new NarrowNode(value, 32)); + } else { + assert toKind == Kind.Long; + assert value.getKind().getStackKind() == Kind.Int; + if (unsigned) { + return builder.append(new ZeroExtendNode(value, 64)); + } else { + return builder.append(new SignExtendNode(value, 64)); + } + } } } diff -r 787a3c7235ef -r b828f1f74625 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Thu Feb 19 11:21:40 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Thu Feb 19 11:22:44 2015 +0100 @@ -22,14 +22,21 @@ */ package com.oracle.graal.hotspot.meta; +import static com.oracle.graal.api.meta.MetaUtil.*; import static com.oracle.graal.compiler.common.GraalOptions.*; +import static com.oracle.graal.replacements.NodeIntrinsificationPhase.*; + +import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.java.*; import com.oracle.graal.java.GraphBuilderConfiguration.DebugInfoMode; +import com.oracle.graal.java.GraphBuilderPlugin.AnnotatedInvocationPlugin; import com.oracle.graal.java.GraphBuilderPlugin.InlineInvokePlugin; import com.oracle.graal.java.GraphBuilderPlugin.LoadFieldPlugin; import com.oracle.graal.lir.phases.*; @@ -39,6 +46,7 @@ import com.oracle.graal.options.DerivedOptionValue.OptionSupplier; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.replacements.*; /** * HotSpot implementation of {@link SuitesProvider}. @@ -104,6 +112,20 @@ return ret; } + NodeIntrinsificationPhase intrinsifier; + + NodeIntrinsificationPhase getIntrinsifier() { + if (intrinsifier == null) { + HotSpotProviders providers = runtime.getHostProviders(); + intrinsifier = new NodeIntrinsificationPhase(providers, providers.getSnippetReflection()); + } + return intrinsifier; + } + + MetaAccessProvider getMetaAccess() { + return runtime.getHostProviders().getMetaAccess(); + } + protected PhaseSuite createGraphBuilderSuite(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Replacements replacements) { PhaseSuite suite = new PhaseSuite<>(); GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(); @@ -127,12 +149,57 @@ if (subst != null) { return subst; } + if (builder.parsingReplacement() && method.getAnnotation(NodeIntrinsic.class) == null) { + return method; + } if (method.hasBytecodes() && method.getCode().length <= TrivialInliningSize.getValue() && depth < InlineDuringParsingMaxDepth.getValue()) { return method; } return null; } }); + config.setAnnotatedInvocationPlugin(new AnnotatedInvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ResolvedJavaMethod method, ValueNode[] args) { + if (builder.parsingReplacement()) { + @SuppressWarnings("hiding") + NodeIntrinsificationPhase intrinsifier = getIntrinsifier(); + NodeIntrinsic intrinsic = intrinsifier.getIntrinsic(method); + if (intrinsic != null) { + Signature sig = method.getSignature(); + Kind returnKind = sig.getReturnKind(); + Stamp stamp = StampFactory.forKind(returnKind); + if (returnKind == Kind.Object) { + JavaType returnType = sig.getReturnType(method.getDeclaringClass()); + if (returnType instanceof ResolvedJavaType) { + stamp = StampFactory.declared((ResolvedJavaType) returnType); + } + } + + ValueNode res = intrinsifier.createIntrinsicNode(Arrays.asList(args), stamp, method, builder.getGraph(), intrinsic); + res = builder.append(res); + if (res.getKind().getStackKind() != Kind.Void) { + builder.push(returnKind.getStackKind(), res); + } + return true; + } else if (intrinsifier.isFoldable(method)) { + ResolvedJavaType[] parameterTypes = resolveJavaTypes(method.toParameterTypes(), method.getDeclaringClass()); + JavaConstant constant = intrinsifier.tryFold(Arrays.asList(args), parameterTypes, method); + if (!COULD_NOT_FOLD.equals(constant)) { + if (constant != null) { + // Replace the invoke with the result of the call + ConstantNode res = builder.append(ConstantNode.forConstant(constant, getMetaAccess())); + builder.push(res.getKind().getStackKind(), builder.append(res)); + } else { + // This must be a void invoke + assert method.getSignature().getReturnKind() == Kind.Void; + } + return true; + } + } + } + return false; + } + }); } suite.appendPhase(new GraphBuilderPhase(config)); return suite; diff -r 787a3c7235ef -r b828f1f74625 graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPlugins.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPlugins.java Thu Feb 19 11:21:40 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2015, 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 com.oracle.graal.java; - -import static com.oracle.graal.java.GraphBuilderContext.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin; -import com.oracle.graal.java.InvocationPlugins.Registration; -import com.oracle.graal.java.InvocationPlugins.Registration.Receiver; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; - -/** - * Provides non-runtime specific {@link InvocationPlugin}s. - */ -public class StandardGraphBuilderPlugins { - public static void registerInvocationPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { - Registration r = new Registration(plugins, metaAccess, Object.class); - r.register1("", Receiver.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode object) { - if (RegisterFinalizerNode.mayHaveFinalizer(object, builder.getAssumptions())) { - builder.append(new RegisterFinalizerNode(object)); - } - return true; - } - }); - - r = new Registration(plugins, metaAccess, Math.class); - r.register1("abs", Float.TYPE, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode value) { - builder.push(Kind.Float, builder.append(new AbsNode(value))); - return true; - } - }); - r.register1("abs", Double.TYPE, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode value) { - builder.push(Kind.Double, builder.append(new AbsNode(value))); - return true; - } - }); - r.register1("sqrt", Double.TYPE, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode value) { - builder.push(Kind.Double, builder.append(new SqrtNode(value))); - return true; - } - }); - - for (Kind kind : Kind.values()) { - if (kind.isPrimitive() && kind != Kind.Void) { - new BoxPlugin(kind).register(metaAccess, plugins); - new UnboxPlugin(kind).register(metaAccess, plugins); - } - } - - GraalDirectivePlugins.registerInvocationPlugins(metaAccess, plugins); - } - - static class BoxPlugin implements InvocationPlugin { - - private final Kind kind; - - BoxPlugin(Kind kind) { - this.kind = kind; - } - - public boolean apply(GraphBuilderContext builder, ValueNode value) { - ResolvedJavaType resultType = builder.getMetaAccess().lookupJavaType(kind.toBoxedJavaClass()); - builder.push(Kind.Object, builder.append(new BoxNode(value, resultType, kind))); - return true; - } - - void register(MetaAccessProvider metaAccess, InvocationPlugins plugins) { - ResolvedJavaMethod method = Registration.resolve(metaAccess, kind.toBoxedJavaClass(), "valueOf", kind.toJavaClass()); - plugins.register(method, this); - } - } - - static class UnboxPlugin implements InvocationPlugin { - - private final Kind kind; - - UnboxPlugin(Kind kind) { - this.kind = kind; - } - - public boolean apply(GraphBuilderContext builder, ValueNode value) { - ValueNode valueNode = UnboxNode.create(builder.getMetaAccess(), builder.getConstantReflection(), nullCheckedValue(builder, value), kind); - builder.push(kind.getStackKind(), builder.append(valueNode)); - return true; - } - - void register(MetaAccessProvider metaAccess, InvocationPlugins plugins) { - String name = kind.toJavaClass().getSimpleName() + "Value"; - ResolvedJavaMethod method = Registration.resolve(metaAccess, kind.toBoxedJavaClass(), name); - plugins.register(method, this); - } - } -} diff -r 787a3c7235ef -r b828f1f74625 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java Thu Feb 19 11:22:44 2015 +0100 @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2015, 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 com.oracle.graal.replacements; + +import static com.oracle.graal.api.code.MemoryBarriers.*; +import static com.oracle.graal.java.GraphBuilderContext.*; +import static java.lang.Character.*; +import sun.misc.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.java.*; +import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin; +import com.oracle.graal.java.InvocationPlugins.Registration; +import com.oracle.graal.java.InvocationPlugins.Registration.Receiver; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * Provides non-runtime specific {@link InvocationPlugin}s. + */ +public class StandardGraphBuilderPlugins { + public static void registerInvocationPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + Registration r = new Registration(plugins, metaAccess, Object.class); + r.register1("", Receiver.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode object) { + if (RegisterFinalizerNode.mayHaveFinalizer(object, builder.getAssumptions())) { + builder.append(new RegisterFinalizerNode(object)); + } + return true; + } + }); + + r = new Registration(plugins, metaAccess, Math.class); + r.register1("abs", Float.TYPE, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode value) { + builder.push(Kind.Float, builder.append(new AbsNode(value))); + return true; + } + }); + r.register1("abs", Double.TYPE, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode value) { + builder.push(Kind.Double, builder.append(new AbsNode(value))); + return true; + } + }); + r.register1("sqrt", Double.TYPE, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode value) { + builder.push(Kind.Double, builder.append(new SqrtNode(value))); + return true; + } + }); + + for (Kind kind : Kind.values()) { + if (kind.isPrimitive() && kind != Kind.Void) { + new BoxPlugin(kind).register(metaAccess, plugins); + new UnboxPlugin(kind).register(metaAccess, plugins); + } + } + + r = new Registration(plugins, metaAccess, Unsafe.class); + for (Kind kind : Kind.values()) { + if ((kind.isPrimitive() && kind != Kind.Void) || kind == Kind.Object) { + String kindName = kind.getJavaName(); + kindName = toUpperCase(kindName.charAt(0)) + kindName.substring(1); + String getName = "get" + kindName; + String putName = "put" + kindName; + r.register3(getName, Receiver.class, Object.class, long.class, new UnsafeGetPlugin(kind, false)); + r.register4(putName, Receiver.class, Object.class, long.class, kind == Kind.Object ? Object.class : kind.toJavaClass(), new UnsafePutPlugin(kind, false)); + r.register3(getName + "Volatile", Receiver.class, Object.class, long.class, new UnsafeGetPlugin(kind, true)); + r.register4(putName + "Volatile", Receiver.class, Object.class, long.class, kind == Kind.Object ? Object.class : kind.toJavaClass(), new UnsafePutPlugin(kind, true)); + if (kind != Kind.Boolean && kind != Kind.Object) { + r.register2(getName, Receiver.class, long.class, new UnsafeGetPlugin(kind, false)); + r.register3(putName, Receiver.class, long.class, kind.toJavaClass(), new UnsafePutPlugin(kind, false)); + } + } + } + GraalDirectivePlugins.registerInvocationPlugins(metaAccess, plugins); + } + + static class BoxPlugin implements InvocationPlugin { + + private final Kind kind; + + BoxPlugin(Kind kind) { + this.kind = kind; + } + + public boolean apply(GraphBuilderContext builder, ValueNode value) { + ResolvedJavaType resultType = builder.getMetaAccess().lookupJavaType(kind.toBoxedJavaClass()); + builder.push(Kind.Object, builder.append(new BoxNode(value, resultType, kind))); + return true; + } + + void register(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + ResolvedJavaMethod method = Registration.resolve(metaAccess, kind.toBoxedJavaClass(), "valueOf", kind.toJavaClass()); + plugins.register(method, this); + } + } + + static class UnboxPlugin implements InvocationPlugin { + + private final Kind kind; + + UnboxPlugin(Kind kind) { + this.kind = kind; + } + + public boolean apply(GraphBuilderContext builder, ValueNode value) { + ValueNode valueNode = UnboxNode.create(builder.getMetaAccess(), builder.getConstantReflection(), nullCheckedValue(builder, value), kind); + builder.push(kind.getStackKind(), builder.append(valueNode)); + return true; + } + + void register(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + String name = kind.toJavaClass().getSimpleName() + "Value"; + ResolvedJavaMethod method = Registration.resolve(metaAccess, kind.toBoxedJavaClass(), name); + plugins.register(method, this); + } + } + + static class UnsafeGetPlugin implements InvocationPlugin { + + private final Kind returnKind; + private final boolean isVolatile; + + public UnsafeGetPlugin(Kind returnKind, boolean isVolatile) { + this.returnKind = returnKind; + this.isVolatile = isVolatile; + } + + public boolean apply(GraphBuilderContext builder, ValueNode ignoredUnsafe, ValueNode address) { + builder.push(returnKind.getStackKind(), builder.append(new DirectReadNode(address, returnKind))); + return true; + } + + public boolean apply(GraphBuilderContext builder, ValueNode ignoredUnsafe, ValueNode object, ValueNode offset) { + if (isVolatile) { + builder.append(new MembarNode(JMM_PRE_VOLATILE_READ)); + } + builder.push(returnKind.getStackKind(), builder.append(new UnsafeLoadNode(object, offset, returnKind, LocationIdentity.ANY_LOCATION))); + if (isVolatile) { + builder.append(new MembarNode(JMM_POST_VOLATILE_READ)); + } + return true; + } + } + + static class UnsafePutPlugin implements InvocationPlugin { + + private final Kind kind; + private final boolean isVolatile; + + public UnsafePutPlugin(Kind kind, boolean isVolatile) { + this.kind = kind; + this.isVolatile = isVolatile; + } + + public boolean apply(GraphBuilderContext builder, ValueNode ignoredUnsafe, ValueNode address, ValueNode value) { + builder.append(new DirectStoreNode(address, value, kind)); + return true; + } + + public boolean apply(GraphBuilderContext builder, ValueNode ignoredUnsafe, ValueNode object, ValueNode offset, ValueNode value) { + if (isVolatile) { + builder.append(new MembarNode(JMM_PRE_VOLATILE_WRITE)); + } + builder.append(new UnsafeStoreNode(object, offset, value, kind, LocationIdentity.ANY_LOCATION)); + if (isVolatile) { + builder.append(new MembarNode(JMM_PRE_VOLATILE_WRITE)); + } + return true; + } + + } +}