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