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