1 /* 2 * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 25 package org.graalvm.compiler.hotspot.meta; 26 27 import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.POINTER_EQ; 28 import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.POINTER_NE; 29 import static org.graalvm.compiler.nodes.ConstantNode.forBoolean; 30 import static jdk.internal.vm.compiler.word.LocationIdentity.any; 31 32 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; 33 import org.graalvm.compiler.bytecode.BridgeMethodUtils; 34 import org.graalvm.compiler.core.common.type.Stamp; 35 import org.graalvm.compiler.core.common.type.StampFactory; 36 import org.graalvm.compiler.debug.GraalError; 37 import org.graalvm.compiler.hotspot.nodes.LoadIndexedPointerNode; 38 import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; 39 import org.graalvm.compiler.hotspot.nodes.type.MetaspacePointerStamp; 40 import org.graalvm.compiler.hotspot.nodes.type.MethodPointerStamp; 41 import org.graalvm.compiler.hotspot.word.HotSpotOperation; 42 import org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode; 43 import org.graalvm.compiler.hotspot.word.PointerCastNode; 44 import org.graalvm.compiler.nodes.LogicNode; 45 import org.graalvm.compiler.nodes.NodeView; 46 import org.graalvm.compiler.nodes.ValueNode; 47 import org.graalvm.compiler.nodes.calc.ConditionalNode; 48 import org.graalvm.compiler.nodes.calc.IsNullNode; 49 import org.graalvm.compiler.nodes.calc.PointerEqualsNode; 50 import org.graalvm.compiler.nodes.extended.GuardingNode; 51 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; 52 import org.graalvm.compiler.nodes.java.LoadIndexedNode; 53 import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; 54 import org.graalvm.compiler.nodes.memory.ReadNode; 55 import org.graalvm.compiler.nodes.memory.address.AddressNode; 56 import org.graalvm.compiler.nodes.type.StampTool; 57 import org.graalvm.compiler.word.WordOperationPlugin; 58 import org.graalvm.compiler.word.WordTypes; 59 import jdk.internal.vm.compiler.word.LocationIdentity; 60 61 import jdk.vm.ci.meta.JavaKind; 62 import jdk.vm.ci.meta.ResolvedJavaMethod; 63 import jdk.vm.ci.meta.ResolvedJavaType; 64 65 /** 66 * Extends {@link WordOperationPlugin} to handle {@linkplain HotSpotOperation HotSpot word 67 * operations}. 68 */ 69 public class HotSpotWordOperationPlugin extends WordOperationPlugin { 70 HotSpotWordOperationPlugin(SnippetReflectionProvider snippetReflection, WordTypes wordTypes) { 71 super(snippetReflection, wordTypes); 72 } 73 74 @Override 75 protected LoadIndexedNode createLoadIndexedNode(ValueNode array, ValueNode index, GuardingNode boundsCheck) { 76 ResolvedJavaType arrayType = StampTool.typeOrNull(array); 77 Stamp componentStamp = wordTypes.getWordStamp(arrayType.getComponentType()); 78 if (componentStamp instanceof MetaspacePointerStamp) { 79 return new LoadIndexedPointerNode(componentStamp, array, index, boundsCheck); 80 } else { 81 return super.createLoadIndexedNode(array, index, boundsCheck); 82 } 83 } 84 85 @Override 86 public boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { 87 if (!wordTypes.isWordOperation(method)) { 88 return false; 89 } 90 91 HotSpotOperation operation = BridgeMethodUtils.getAnnotation(HotSpotOperation.class, method); 92 if (operation == null) { 93 processWordOperation(b, args, wordTypes.getWordOperation(method, b.getMethod().getDeclaringClass())); 94 return true; 95 } 96 processHotSpotWordOperation(b, method, args, operation); 97 return true; 98 } 99 100 protected void processHotSpotWordOperation(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args, HotSpotOperation operation) { 101 JavaKind returnKind = method.getSignature().getReturnKind(); 102 switch (operation.opcode()) { 103 case POINTER_EQ: 104 case POINTER_NE: 105 assert args.length == 2; 106 HotspotOpcode opcode = operation.opcode(); 107 ValueNode left = args[0]; 108 ValueNode right = args[1]; 109 assert left.stamp(NodeView.DEFAULT) instanceof MetaspacePointerStamp : left + " " + left.stamp(NodeView.DEFAULT); 110 assert right.stamp(NodeView.DEFAULT) instanceof MetaspacePointerStamp : right + " " + right.stamp(NodeView.DEFAULT); 111 assert opcode == POINTER_EQ || opcode == POINTER_NE; 112 113 PointerEqualsNode comparison = b.add(new PointerEqualsNode(left, right)); 114 ValueNode eqValue = b.add(forBoolean(opcode == POINTER_EQ)); 115 ValueNode neValue = b.add(forBoolean(opcode == POINTER_NE)); 116 b.addPush(returnKind, ConditionalNode.create(comparison, eqValue, neValue, NodeView.DEFAULT)); 117 break; 118 119 case IS_NULL: 120 assert args.length == 1; 121 ValueNode pointer = args[0]; 122 assert pointer.stamp(NodeView.DEFAULT) instanceof MetaspacePointerStamp; 123 124 LogicNode isNull = b.add(IsNullNode.create(pointer)); 125 b.addPush(returnKind, ConditionalNode.create(isNull, b.add(forBoolean(true)), b.add(forBoolean(false)), NodeView.DEFAULT)); 126 break; 127 128 case FROM_POINTER: 129 assert args.length == 1; 130 b.addPush(returnKind, new PointerCastNode(StampFactory.forKind(wordKind), args[0])); 131 break; 132 133 case TO_KLASS_POINTER: 134 assert args.length == 1; 135 b.addPush(returnKind, new PointerCastNode(KlassPointerStamp.klass(), args[0])); 136 break; 137 138 case TO_METHOD_POINTER: 139 assert args.length == 1; 140 b.addPush(returnKind, new PointerCastNode(MethodPointerStamp.method(), args[0])); 141 break; 142 143 case READ_KLASS_POINTER: 144 assert args.length == 2 || args.length == 3; 145 Stamp readStamp = KlassPointerStamp.klass(); 146 AddressNode address = makeAddress(b, args[0], args[1]); 147 LocationIdentity location; 148 if (args.length == 2) { 149 location = any(); 150 } else { 151 assert args[2].isConstant(); 152 location = snippetReflection.asObject(LocationIdentity.class, args[2].asJavaConstant()); 153 } 154 ReadNode read = b.add(new ReadNode(address, location, readStamp, BarrierType.NONE)); 155 b.push(returnKind, read); 156 break; 157 158 default: 159 throw GraalError.shouldNotReachHere("unknown operation: " + operation.opcode()); 160 } 161 } 162 }