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.hotspot.meta; 024 025import static com.oracle.graal.hotspot.word.HotSpotOperation.HotspotOpcode.*; 026import static com.oracle.graal.nodes.ConstantNode.*; 027import static jdk.internal.jvmci.meta.LocationIdentity.*; 028import jdk.internal.jvmci.common.*; 029import jdk.internal.jvmci.meta.*; 030 031import com.oracle.graal.api.replacements.*; 032import com.oracle.graal.compiler.common.type.*; 033import com.oracle.graal.graphbuilderconf.*; 034import com.oracle.graal.hotspot.nodes.*; 035import com.oracle.graal.hotspot.nodes.type.*; 036import com.oracle.graal.hotspot.word.*; 037import com.oracle.graal.hotspot.word.HotSpotOperation.HotspotOpcode; 038import com.oracle.graal.nodes.*; 039import com.oracle.graal.nodes.calc.*; 040import com.oracle.graal.nodes.java.*; 041import com.oracle.graal.nodes.memory.HeapAccess.BarrierType; 042import com.oracle.graal.nodes.memory.*; 043import com.oracle.graal.nodes.memory.address.*; 044import com.oracle.graal.nodes.type.*; 045import com.oracle.graal.replacements.*; 046 047/** 048 * Extends {@link WordOperationPlugin} to handle {@linkplain HotSpotOperation HotSpot word 049 * operations}. 050 */ 051class HotSpotWordOperationPlugin extends WordOperationPlugin { 052 053 public HotSpotWordOperationPlugin(SnippetReflectionProvider snippetReflection, HotSpotWordTypes wordTypes) { 054 super(snippetReflection, wordTypes); 055 } 056 057 HotSpotWordTypes wordTypes() { 058 return (HotSpotWordTypes) wordTypes; 059 } 060 061 @Override 062 protected LoadIndexedNode createLoadIndexedNode(ValueNode array, ValueNode index) { 063 ResolvedJavaType arrayType = StampTool.typeOrNull(array); 064 Stamp componentStamp = wordTypes.getWordStamp(arrayType.getComponentType()); 065 if (componentStamp instanceof MetaspacePointerStamp) { 066 return new LoadIndexedPointerNode(componentStamp, array, index); 067 } else { 068 return super.createLoadIndexedNode(array, index); 069 } 070 } 071 072 @Override 073 public boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { 074 if (!wordTypes.isWordOperation(method)) { 075 return false; 076 } 077 078 HotSpotOperation operation = method.getAnnotation(HotSpotOperation.class); 079 if (operation == null) { 080 processWordOperation(b, args, wordTypes.getWordOperation(method, b.getMethod().getDeclaringClass())); 081 return true; 082 } 083 processHotSpotWordOperation(b, method, args, operation); 084 return true; 085 } 086 087 protected void processHotSpotWordOperation(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args, HotSpotOperation operation) { 088 Kind returnKind = method.getSignature().getReturnKind(); 089 switch (operation.opcode()) { 090 case POINTER_EQ: 091 case POINTER_NE: 092 assert args.length == 2; 093 HotspotOpcode opcode = operation.opcode(); 094 ValueNode left = args[0]; 095 ValueNode right = args[1]; 096 assert left.stamp() instanceof MetaspacePointerStamp : left + " " + left.stamp(); 097 assert right.stamp() instanceof MetaspacePointerStamp : right + " " + right.stamp(); 098 assert opcode == POINTER_EQ || opcode == POINTER_NE; 099 100 PointerEqualsNode comparison = b.add(new PointerEqualsNode(left, right)); 101 ValueNode eqValue = b.add(forBoolean(opcode == POINTER_EQ)); 102 ValueNode neValue = b.add(forBoolean(opcode == POINTER_NE)); 103 b.addPush(returnKind, new ConditionalNode(comparison, eqValue, neValue)); 104 break; 105 106 case IS_NULL: 107 assert args.length == 1; 108 ValueNode pointer = args[0]; 109 assert pointer.stamp() instanceof MetaspacePointerStamp; 110 111 IsNullNode isNull = b.add(new IsNullNode(pointer)); 112 b.addPush(returnKind, new ConditionalNode(isNull, b.add(forBoolean(true)), b.add(forBoolean(false)))); 113 break; 114 115 case FROM_POINTER: 116 assert args.length == 1; 117 b.addPush(returnKind, new PointerCastNode(StampFactory.forKind(wordKind), args[0])); 118 break; 119 120 case TO_KLASS_POINTER: 121 assert args.length == 1; 122 b.addPush(returnKind, new PointerCastNode(wordTypes().getKlassPointerStamp(), args[0])); 123 break; 124 125 case TO_METHOD_POINTER: 126 assert args.length == 1; 127 b.addPush(returnKind, new PointerCastNode(wordTypes().getMethodPointerStamp(), args[0])); 128 break; 129 130 case READ_KLASS_POINTER: 131 assert args.length == 2 || args.length == 3; 132 Stamp readStamp = wordTypes().getKlassPointerStamp(); 133 AddressNode address = makeAddress(b, args[0], args[1]); 134 LocationIdentity location; 135 if (args.length == 2) { 136 location = any(); 137 } else { 138 assert args[2].isConstant(); 139 location = snippetReflection.asObject(LocationIdentity.class, args[2].asJavaConstant()); 140 } 141 ReadNode read = b.add(new ReadNode(address, location, readStamp, BarrierType.NONE)); 142 /* 143 * The read must not float outside its block otherwise it may float above an 144 * explicit zero check on its base address. 145 */ 146 read.setGuard(AbstractBeginNode.prevBegin(read)); 147 b.push(returnKind, read); 148 break; 149 150 default: 151 throw JVMCIError.shouldNotReachHere("unknown operation: " + operation.opcode()); 152 } 153 } 154}