001/* 002 * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.replacements.amd64; 024 025import jdk.internal.jvmci.amd64.*; 026import jdk.internal.jvmci.meta.*; 027import static com.oracle.graal.compiler.target.Backend.*; 028import static com.oracle.graal.replacements.amd64.AMD64MathIntrinsicNode.Operation.*; 029import sun.misc.*; 030 031import com.oracle.graal.compiler.common.spi.*; 032import com.oracle.graal.graphbuilderconf.*; 033import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; 034import com.oracle.graal.graphbuilderconf.InvocationPlugin.Receiver; 035import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration; 036import com.oracle.graal.nodes.*; 037import com.oracle.graal.nodes.java.*; 038import com.oracle.graal.nodes.memory.address.*; 039import com.oracle.graal.replacements.*; 040import com.oracle.graal.replacements.StandardGraphBuilderPlugins.*; 041 042public class AMD64GraphBuilderPlugins { 043 044 public static void register(Plugins plugins, ForeignCallsProvider foreignCalls, AMD64 arch) { 045 InvocationPlugins invocationPlugins = plugins.getInvocationPlugins(); 046 registerIntegerLongPlugins(invocationPlugins, IntegerSubstitutions.class, Kind.Int, arch); 047 registerIntegerLongPlugins(invocationPlugins, LongSubstitutions.class, Kind.Long, arch); 048 registerUnsafePlugins(invocationPlugins); 049 registerMathPlugins(invocationPlugins, foreignCalls); 050 } 051 052 private static void registerIntegerLongPlugins(InvocationPlugins plugins, Class<?> substituteDeclaringClass, Kind kind, AMD64 arch) { 053 Class<?> declaringClass = kind.toBoxedJavaClass(); 054 Class<?> type = kind.toJavaClass(); 055 Registration r = new Registration(plugins, declaringClass); 056 if (arch.getFlags().contains(AMD64.Flag.UseCountLeadingZerosInstruction)) { 057 r.register1("numberOfLeadingZeros", type, new InvocationPlugin() { 058 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { 059 ValueNode folded = AMD64CountLeadingZerosNode.tryFold(value); 060 if (folded != null) { 061 b.addPush(Kind.Int, folded); 062 } else { 063 b.addPush(Kind.Int, new AMD64CountLeadingZerosNode(value)); 064 } 065 return true; 066 } 067 }); 068 } else { 069 r.registerMethodSubstitution(substituteDeclaringClass, "numberOfLeadingZeros", type); 070 } 071 if (arch.getFlags().contains(AMD64.Flag.UseCountTrailingZerosInstruction)) { 072 r.register1("numberOfTrailingZeros", type, new InvocationPlugin() { 073 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { 074 ValueNode folded = AMD64CountTrailingZerosNode.tryFold(value); 075 if (folded != null) { 076 b.addPush(Kind.Int, folded); 077 } else { 078 b.addPush(Kind.Int, new AMD64CountTrailingZerosNode(value)); 079 } 080 return true; 081 } 082 }); 083 } else { 084 r.registerMethodSubstitution(substituteDeclaringClass, "numberOfTrailingZeros", type); 085 } 086 } 087 088 private static void registerMathPlugins(InvocationPlugins plugins, ForeignCallsProvider foreignCalls) { 089 Registration r = new Registration(plugins, Math.class); 090 r.register1("log", Double.TYPE, new InvocationPlugin() { 091 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { 092 b.push(Kind.Double, b.recursiveAppend(AMD64MathIntrinsicNode.create(value, LOG))); 093 return true; 094 } 095 }); 096 r.register1("log10", Double.TYPE, new InvocationPlugin() { 097 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { 098 b.push(Kind.Double, b.recursiveAppend(AMD64MathIntrinsicNode.create(value, LOG10))); 099 return true; 100 } 101 }); 102 r.registerMethodSubstitution(AMD64MathSubstitutions.class, "sin", double.class); 103 r.registerMethodSubstitution(AMD64MathSubstitutions.class, "cos", double.class); 104 r.registerMethodSubstitution(AMD64MathSubstitutions.class, "tan", double.class); 105 r.registerMethodSubstitution(AMD64MathSubstitutions.class, "pow", double.class, double.class); 106 r.register1("exp", Double.TYPE, new ForeignCallPlugin(foreignCalls, ARITHMETIC_EXP)); 107 } 108 109 private static void registerUnsafePlugins(InvocationPlugins plugins) { 110 Registration r = new Registration(plugins, Unsafe.class); 111 112 for (Kind kind : new Kind[]{Kind.Int, Kind.Long, Kind.Object}) { 113 Class<?> javaClass = kind == Kind.Object ? Object.class : kind.toJavaClass(); 114 115 r.register4("getAndSet" + kind.name(), Receiver.class, Object.class, long.class, javaClass, new InvocationPlugin() { 116 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode object, ValueNode offset, ValueNode value) { 117 // Emits a null-check for the otherwise unused receiver 118 unsafe.get(); 119 b.addPush(kind, new AtomicReadAndWriteNode(object, offset, value, kind, LocationIdentity.any())); 120 b.getGraph().markUnsafeAccess(); 121 return true; 122 } 123 }); 124 if (kind != Kind.Object) { 125 r.register4("getAndAdd" + kind.name(), Receiver.class, Object.class, long.class, javaClass, new InvocationPlugin() { 126 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode object, ValueNode offset, ValueNode delta) { 127 // Emits a null-check for the otherwise unused receiver 128 unsafe.get(); 129 AddressNode address = b.add(new OffsetAddressNode(object, offset)); 130 b.addPush(kind, new AtomicReadAndAddNode(address, delta, LocationIdentity.any())); 131 b.getGraph().markUnsafeAccess(); 132 return true; 133 } 134 }); 135 } 136 } 137 138 for (Kind kind : new Kind[]{Kind.Char, Kind.Short, Kind.Int, Kind.Long}) { 139 Class<?> javaClass = kind.toJavaClass(); 140 r.registerOptional3("get" + kind.name() + "Unaligned", Receiver.class, Object.class, long.class, new UnsafeGetPlugin(kind, false)); 141 r.registerOptional4("put" + kind.name() + "Unaligned", Receiver.class, Object.class, long.class, javaClass, new UnsafePutPlugin(kind, false)); 142 } 143 } 144}