1 /* 2 * Copyright (c) 2013, 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.replacements.test; 26 27 import org.graalvm.compiler.api.replacements.Snippet; 28 import org.graalvm.compiler.nodes.NamedLocationIdentity; 29 import org.graalvm.compiler.nodes.NodeView; 30 import org.graalvm.compiler.nodes.ReturnNode; 31 import org.graalvm.compiler.nodes.StructuredGraph; 32 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 33 import org.graalvm.compiler.nodes.ValueNode; 34 import org.graalvm.compiler.nodes.calc.ConvertNode; 35 import org.graalvm.compiler.nodes.calc.SignExtendNode; 36 import org.graalvm.compiler.nodes.extended.JavaReadNode; 37 import org.graalvm.compiler.nodes.extended.JavaWriteNode; 38 import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; 39 import org.graalvm.compiler.phases.OptimisticOptimizations; 40 import org.graalvm.compiler.phases.tiers.HighTierContext; 41 import org.graalvm.compiler.word.Word; 42 import org.graalvm.compiler.word.WordCastNode; 43 import jdk.internal.vm.compiler.word.LocationIdentity; 44 import jdk.internal.vm.compiler.word.Pointer; 45 import jdk.internal.vm.compiler.word.WordFactory; 46 import org.junit.Assert; 47 import org.junit.Test; 48 49 import jdk.vm.ci.code.BytecodeFrame; 50 import jdk.vm.ci.code.TargetDescription; 51 import jdk.vm.ci.meta.JavaKind; 52 53 /** 54 * Tests for the {@link Pointer} read and write operations. 55 */ 56 public class PointerTest extends SnippetsTest { 57 58 private static final LocationIdentity ID = NamedLocationIdentity.mutable("ID"); 59 private static final JavaKind[] KINDS = new JavaKind[]{JavaKind.Byte, JavaKind.Char, JavaKind.Short, JavaKind.Int, JavaKind.Long, JavaKind.Float, JavaKind.Double, JavaKind.Object}; 60 private final TargetDescription target; 61 PointerTest()62 public PointerTest() { 63 target = getCodeCache().getTarget(); 64 } 65 66 @Test testRead1()67 public void testRead1() { 68 for (JavaKind kind : KINDS) { 69 assertRead(parseEager("read" + kind.name() + "1", AllowAssumptions.YES), kind, true, ID); 70 } 71 } 72 73 @Test testRead2()74 public void testRead2() { 75 for (JavaKind kind : KINDS) { 76 assertRead(parseEager("read" + kind.name() + "2", AllowAssumptions.YES), kind, true, ID); 77 } 78 } 79 80 @Test testRead3()81 public void testRead3() { 82 for (JavaKind kind : KINDS) { 83 assertRead(parseEager("read" + kind.name() + "3", AllowAssumptions.YES), kind, true, LocationIdentity.any()); 84 } 85 } 86 87 @Test testWrite1()88 public void testWrite1() { 89 for (JavaKind kind : KINDS) { 90 assertWrite(parseEager("write" + kind.name() + "1", AllowAssumptions.YES), kind, true, ID); 91 } 92 } 93 94 @Test testWrite2()95 public void testWrite2() { 96 for (JavaKind kind : KINDS) { 97 assertWrite(parseEager("write" + kind.name() + "2", AllowAssumptions.YES), kind, true, ID); 98 } 99 } 100 101 @Test testWrite3()102 public void testWrite3() { 103 for (JavaKind kind : KINDS) { 104 assertWrite(parseEager("write" + kind.name() + "3", AllowAssumptions.YES), kind, true, LocationIdentity.any()); 105 } 106 } 107 assertRead(StructuredGraph graph, JavaKind kind, boolean indexConvert, LocationIdentity locationIdentity)108 private void assertRead(StructuredGraph graph, JavaKind kind, boolean indexConvert, LocationIdentity locationIdentity) { 109 WordCastNode cast = (WordCastNode) graph.start().next(); 110 111 JavaReadNode read = (JavaReadNode) cast.next(); 112 Assert.assertEquals(kind.getStackKind(), read.stamp(NodeView.DEFAULT).getStackKind()); 113 114 OffsetAddressNode address = (OffsetAddressNode) read.getAddress(); 115 Assert.assertEquals(cast, address.getBase()); 116 Assert.assertEquals(graph.getParameter(0), cast.getInput()); 117 Assert.assertEquals(target.wordJavaKind, cast.stamp(NodeView.DEFAULT).getStackKind()); 118 119 Assert.assertEquals(locationIdentity, read.getLocationIdentity()); 120 121 if (indexConvert) { 122 SignExtendNode convert = (SignExtendNode) address.getOffset(); 123 Assert.assertEquals(convert.getInputBits(), 32); 124 Assert.assertEquals(convert.getResultBits(), 64); 125 Assert.assertEquals(graph.getParameter(1), convert.getValue()); 126 } else { 127 Assert.assertEquals(graph.getParameter(1), address.getOffset()); 128 } 129 130 ReturnNode ret = (ReturnNode) read.next(); 131 Assert.assertEquals(read, ret.result()); 132 } 133 assertWrite(StructuredGraph graph, JavaKind kind, boolean indexConvert, LocationIdentity locationIdentity)134 private void assertWrite(StructuredGraph graph, JavaKind kind, boolean indexConvert, LocationIdentity locationIdentity) { 135 WordCastNode cast = (WordCastNode) graph.start().next(); 136 137 JavaWriteNode write = (JavaWriteNode) cast.next(); 138 ValueNode valueNode = write.value(); 139 if (kind != kind.getStackKind()) { 140 while (valueNode instanceof ConvertNode) { 141 valueNode = ((ConvertNode) valueNode).getValue(); 142 } 143 } 144 Assert.assertEquals(graph.getParameter(2), valueNode); 145 Assert.assertEquals(BytecodeFrame.AFTER_BCI, write.stateAfter().bci); 146 147 OffsetAddressNode address = (OffsetAddressNode) write.getAddress(); 148 Assert.assertEquals(cast, address.getBase()); 149 Assert.assertEquals(graph.getParameter(0), cast.getInput()); 150 Assert.assertEquals(target.wordJavaKind, cast.stamp(NodeView.DEFAULT).getStackKind()); 151 152 Assert.assertEquals(locationIdentity, write.getKilledLocationIdentity()); 153 154 if (indexConvert) { 155 SignExtendNode convert = (SignExtendNode) address.getOffset(); 156 Assert.assertEquals(convert.getInputBits(), 32); 157 Assert.assertEquals(convert.getResultBits(), 64); 158 Assert.assertEquals(graph.getParameter(1), convert.getValue()); 159 } else { 160 Assert.assertEquals(graph.getParameter(1), address.getOffset()); 161 } 162 163 ReturnNode ret = (ReturnNode) write.next(); 164 Assert.assertEquals(null, ret.result()); 165 } 166 167 @Snippet readByte1(Object o, int offset)168 public static byte readByte1(Object o, int offset) { 169 return Word.objectToTrackedPointer(o).readByte(offset, ID); 170 } 171 172 @Snippet readByte2(Object o, int offset)173 public static byte readByte2(Object o, int offset) { 174 return Word.objectToTrackedPointer(o).readByte(WordFactory.signed(offset), ID); 175 } 176 177 @Snippet readByte3(Object o, int offset)178 public static byte readByte3(Object o, int offset) { 179 return Word.objectToTrackedPointer(o).readByte(offset); 180 } 181 182 @Snippet writeByte1(Object o, int offset, byte value)183 public static void writeByte1(Object o, int offset, byte value) { 184 Word.objectToTrackedPointer(o).writeByte(offset, value, ID); 185 } 186 187 @Snippet writeByte2(Object o, int offset, byte value)188 public static void writeByte2(Object o, int offset, byte value) { 189 Word.objectToTrackedPointer(o).writeByte(WordFactory.signed(offset), value, ID); 190 } 191 192 @Snippet writeByte3(Object o, int offset, byte value)193 public static void writeByte3(Object o, int offset, byte value) { 194 Word.objectToTrackedPointer(o).writeByte(offset, value); 195 } 196 197 @Snippet readChar1(Object o, int offset)198 public static char readChar1(Object o, int offset) { 199 return Word.objectToTrackedPointer(o).readChar(offset, ID); 200 } 201 202 @Snippet readChar2(Object o, int offset)203 public static char readChar2(Object o, int offset) { 204 return Word.objectToTrackedPointer(o).readChar(WordFactory.signed(offset), ID); 205 } 206 207 @Snippet readChar3(Object o, int offset)208 public static char readChar3(Object o, int offset) { 209 return Word.objectToTrackedPointer(o).readChar(offset); 210 } 211 212 @Snippet writeChar1(Object o, int offset, char value)213 public static void writeChar1(Object o, int offset, char value) { 214 Word.objectToTrackedPointer(o).writeChar(offset, value, ID); 215 } 216 217 @Snippet writeChar2(Object o, int offset, char value)218 public static void writeChar2(Object o, int offset, char value) { 219 Word.objectToTrackedPointer(o).writeChar(WordFactory.signed(offset), value, ID); 220 } 221 222 @Snippet writeChar3(Object o, int offset, char value)223 public static void writeChar3(Object o, int offset, char value) { 224 Word.objectToTrackedPointer(o).writeChar(offset, value); 225 } 226 227 @Snippet readShort1(Object o, int offset)228 public static short readShort1(Object o, int offset) { 229 return Word.objectToTrackedPointer(o).readShort(offset, ID); 230 } 231 232 @Snippet readShort2(Object o, int offset)233 public static short readShort2(Object o, int offset) { 234 return Word.objectToTrackedPointer(o).readShort(WordFactory.signed(offset), ID); 235 } 236 237 @Snippet readShort3(Object o, int offset)238 public static short readShort3(Object o, int offset) { 239 return Word.objectToTrackedPointer(o).readShort(offset); 240 } 241 242 @Snippet writeShort1(Object o, int offset, short value)243 public static void writeShort1(Object o, int offset, short value) { 244 Word.objectToTrackedPointer(o).writeShort(offset, value, ID); 245 } 246 247 @Snippet writeShort2(Object o, int offset, short value)248 public static void writeShort2(Object o, int offset, short value) { 249 Word.objectToTrackedPointer(o).writeShort(WordFactory.signed(offset), value, ID); 250 } 251 252 @Snippet writeShort3(Object o, int offset, short value)253 public static void writeShort3(Object o, int offset, short value) { 254 Word.objectToTrackedPointer(o).writeShort(offset, value); 255 } 256 257 @Snippet readInt1(Object o, int offset)258 public static int readInt1(Object o, int offset) { 259 return Word.objectToTrackedPointer(o).readInt(offset, ID); 260 } 261 262 @Snippet readInt2(Object o, int offset)263 public static int readInt2(Object o, int offset) { 264 return Word.objectToTrackedPointer(o).readInt(WordFactory.signed(offset), ID); 265 } 266 267 @Snippet readInt3(Object o, int offset)268 public static int readInt3(Object o, int offset) { 269 return Word.objectToTrackedPointer(o).readInt(offset); 270 } 271 272 @Snippet writeInt1(Object o, int offset, int value)273 public static void writeInt1(Object o, int offset, int value) { 274 Word.objectToTrackedPointer(o).writeInt(offset, value, ID); 275 } 276 277 @Snippet writeInt2(Object o, int offset, int value)278 public static void writeInt2(Object o, int offset, int value) { 279 Word.objectToTrackedPointer(o).writeInt(WordFactory.signed(offset), value, ID); 280 } 281 282 @Snippet writeInt3(Object o, int offset, int value)283 public static void writeInt3(Object o, int offset, int value) { 284 Word.objectToTrackedPointer(o).writeInt(offset, value); 285 } 286 287 @Snippet readLong1(Object o, int offset)288 public static long readLong1(Object o, int offset) { 289 return Word.objectToTrackedPointer(o).readLong(offset, ID); 290 } 291 292 @Snippet readLong2(Object o, int offset)293 public static long readLong2(Object o, int offset) { 294 return Word.objectToTrackedPointer(o).readLong(WordFactory.signed(offset), ID); 295 } 296 297 @Snippet readLong3(Object o, int offset)298 public static long readLong3(Object o, int offset) { 299 return Word.objectToTrackedPointer(o).readLong(offset); 300 } 301 302 @Snippet writeLong1(Object o, int offset, long value)303 public static void writeLong1(Object o, int offset, long value) { 304 Word.objectToTrackedPointer(o).writeLong(offset, value, ID); 305 } 306 307 @Snippet writeLong2(Object o, int offset, long value)308 public static void writeLong2(Object o, int offset, long value) { 309 Word.objectToTrackedPointer(o).writeLong(WordFactory.signed(offset), value, ID); 310 } 311 312 @Snippet writeLong3(Object o, int offset, long value)313 public static void writeLong3(Object o, int offset, long value) { 314 Word.objectToTrackedPointer(o).writeLong(offset, value); 315 } 316 317 @Snippet readFloat1(Object o, int offset)318 public static float readFloat1(Object o, int offset) { 319 return Word.objectToTrackedPointer(o).readFloat(offset, ID); 320 } 321 322 @Snippet readFloat2(Object o, int offset)323 public static float readFloat2(Object o, int offset) { 324 return Word.objectToTrackedPointer(o).readFloat(WordFactory.signed(offset), ID); 325 } 326 327 @Snippet readFloat3(Object o, int offset)328 public static float readFloat3(Object o, int offset) { 329 return Word.objectToTrackedPointer(o).readFloat(offset); 330 } 331 332 @Snippet writeFloat1(Object o, int offset, float value)333 public static void writeFloat1(Object o, int offset, float value) { 334 Word.objectToTrackedPointer(o).writeFloat(offset, value, ID); 335 } 336 337 @Snippet writeFloat2(Object o, int offset, float value)338 public static void writeFloat2(Object o, int offset, float value) { 339 Word.objectToTrackedPointer(o).writeFloat(WordFactory.signed(offset), value, ID); 340 } 341 342 @Snippet writeFloat3(Object o, int offset, float value)343 public static void writeFloat3(Object o, int offset, float value) { 344 Word.objectToTrackedPointer(o).writeFloat(offset, value); 345 } 346 347 @Snippet readDouble1(Object o, int offset)348 public static double readDouble1(Object o, int offset) { 349 return Word.objectToTrackedPointer(o).readDouble(offset, ID); 350 } 351 352 @Snippet readDouble2(Object o, int offset)353 public static double readDouble2(Object o, int offset) { 354 return Word.objectToTrackedPointer(o).readDouble(WordFactory.signed(offset), ID); 355 } 356 357 @Snippet readDouble3(Object o, int offset)358 public static double readDouble3(Object o, int offset) { 359 return Word.objectToTrackedPointer(o).readDouble(offset); 360 } 361 362 @Snippet writeDouble1(Object o, int offset, double value)363 public static void writeDouble1(Object o, int offset, double value) { 364 Word.objectToTrackedPointer(o).writeDouble(offset, value, ID); 365 } 366 367 @Snippet writeDouble2(Object o, int offset, double value)368 public static void writeDouble2(Object o, int offset, double value) { 369 Word.objectToTrackedPointer(o).writeDouble(WordFactory.signed(offset), value, ID); 370 } 371 372 @Snippet writeDouble3(Object o, int offset, double value)373 public static void writeDouble3(Object o, int offset, double value) { 374 Word.objectToTrackedPointer(o).writeDouble(offset, value); 375 } 376 377 @Snippet readObject1(Object o, int offset)378 public static Object readObject1(Object o, int offset) { 379 return Word.objectToTrackedPointer(o).readObject(offset, ID); 380 } 381 382 @Snippet readObject2(Object o, int offset)383 public static Object readObject2(Object o, int offset) { 384 return Word.objectToTrackedPointer(o).readObject(WordFactory.signed(offset), ID); 385 } 386 387 @Snippet readObject3(Object o, int offset)388 public static Object readObject3(Object o, int offset) { 389 return Word.objectToTrackedPointer(o).readObject(offset); 390 } 391 392 @Snippet writeObject1(Object o, int offset, Object value)393 public static void writeObject1(Object o, int offset, Object value) { 394 Word.objectToTrackedPointer(o).writeObject(offset, value, ID); 395 } 396 397 @Snippet writeObject2(Object o, int offset, Object value)398 public static void writeObject2(Object o, int offset, Object value) { 399 Word.objectToTrackedPointer(o).writeObject(WordFactory.signed(offset), value, ID); 400 } 401 402 @Snippet writeObject3(Object o, int offset, Object value)403 public static void writeObject3(Object o, int offset, Object value) { 404 Word.objectToTrackedPointer(o).writeObject(offset, value); 405 } 406 assertNumWordCasts(String snippetName, int expectedWordCasts)407 private void assertNumWordCasts(String snippetName, int expectedWordCasts) { 408 HighTierContext context = new HighTierContext(getProviders(), null, OptimisticOptimizations.ALL); 409 410 StructuredGraph graph = parseEager(snippetName, AllowAssumptions.YES); 411 this.createCanonicalizerPhase().apply(graph, context); 412 Assert.assertEquals(expectedWordCasts, graph.getNodes().filter(WordCastNode.class).count()); 413 } 414 415 @Test testUnusedFromObject()416 public void testUnusedFromObject() { 417 assertNumWordCasts("unusedFromObject", 0); 418 } 419 420 @Snippet unusedFromObject(Object o)421 public static void unusedFromObject(Object o) { 422 Word.objectToTrackedPointer(o); 423 } 424 425 @Test testUnusedRawValue()426 public void testUnusedRawValue() { 427 assertNumWordCasts("unusedRawValue", 0); 428 } 429 430 @Snippet unusedRawValue(Object o)431 public static void unusedRawValue(Object o) { 432 Word.objectToTrackedPointer(o).rawValue(); 433 } 434 435 @Test testUsedRawValue()436 public void testUsedRawValue() { 437 assertNumWordCasts("usedRawValue", 1); 438 } 439 440 @Snippet usedRawValue(Object o)441 public static long usedRawValue(Object o) { 442 return Word.objectToTrackedPointer(o).rawValue(); 443 } 444 445 @Test testUnusedToObject()446 public void testUnusedToObject() { 447 assertNumWordCasts("unusedToObject", 0); 448 } 449 450 @Snippet unusedToObject(Word w)451 public static void unusedToObject(Word w) { 452 w.toObject(); 453 } 454 455 @Test testUsedToObject()456 public void testUsedToObject() { 457 assertNumWordCasts("usedToObject", 1); 458 } 459 460 @Snippet usedToObject(Word w)461 public static Object usedToObject(Word w) { 462 return w.toObject(); 463 } 464 } 465