1 /* 2 * Copyright (c) 2018, 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.core.test; 26 27 import java.util.ArrayList; 28 import java.util.List; 29 30 import org.junit.Test; 31 import org.junit.runner.RunWith; 32 import org.junit.runners.Parameterized; 33 import org.objectweb.asm.ClassWriter; 34 import org.objectweb.asm.FieldVisitor; 35 import org.objectweb.asm.MethodVisitor; 36 import org.objectweb.asm.Type; 37 38 import jdk.vm.ci.meta.JavaKind; 39 40 @RunWith(Parameterized.class) 41 public class SubWordFieldStoreTest extends CustomizedBytecodePatternTest { 42 43 @Parameterized.Parameters(name = "{0}, {1}, {2}, {3}") data()44 public static List<Object[]> data() { 45 ArrayList<Object[]> ret = new ArrayList<>(); 46 for (int i : new int[]{0xFFFF0000, 0xFFFF0001, 0x0000FFFF, 0x01020304}) { 47 for (boolean unsafeStore : new boolean[]{false, true}) { 48 for (boolean unsafeLoad : new boolean[]{false, true}) { 49 ret.add(new Object[]{JavaKind.Boolean, i, unsafeStore, unsafeLoad}); 50 ret.add(new Object[]{JavaKind.Byte, i, unsafeStore, unsafeLoad}); 51 ret.add(new Object[]{JavaKind.Short, i, unsafeStore, unsafeLoad}); 52 ret.add(new Object[]{JavaKind.Char, i, unsafeStore, unsafeLoad}); 53 } 54 } 55 } 56 return ret; 57 } 58 59 private static final String SNIPPET = "snippet"; 60 61 private final JavaKind kind; 62 private final int value; 63 private final boolean unsafeStore; 64 private final boolean unsafeLoad; 65 SubWordFieldStoreTest(JavaKind kind, int value, boolean unsafeStore, boolean unsafeLoad)66 public SubWordFieldStoreTest(JavaKind kind, int value, boolean unsafeStore, boolean unsafeLoad) { 67 this.kind = kind; 68 this.value = value; 69 this.unsafeStore = unsafeStore; 70 this.unsafeLoad = unsafeLoad; 71 } 72 73 @Test testFieldStore()74 public void testFieldStore() throws ClassNotFoundException { 75 Class<?> testClass = getClass(SubWordFieldStoreTest.class.getName() + "$" + kind.toString() + "Getter"); 76 test(getResolvedJavaMethod(testClass, SNIPPET), null); 77 } 78 79 @Override generateClass(String internalClassName)80 protected byte[] generateClass(String internalClassName) { 81 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); 82 cw.visit(52, ACC_SUPER | ACC_PUBLIC, internalClassName, null, "java/lang/Object", null); 83 84 final String fieldName = "field"; 85 final String fieldDescriptor = Character.toString(kind.getTypeChar()); 86 87 FieldVisitor field = cw.visitField(ACC_PUBLIC | ACC_STATIC, fieldName, fieldDescriptor, null, value); 88 field.visitEnd(); 89 90 MethodVisitor snippet = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, SNIPPET, "()Z", null, new String[]{"java/lang/NoSuchFieldException"}); 91 snippet.visitCode(); 92 93 if (unsafeStore) { 94 snippet.visitLdcInsn(Type.getObjectType(internalClassName)); 95 snippet.visitLdcInsn(fieldName); 96 snippet.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getField", "(Ljava/lang/String;)Ljava/lang/reflect/Field;", false); 97 snippet.visitVarInsn(ASTORE, 0); 98 99 SubWordTestUtil.getUnsafe(snippet); 100 snippet.visitVarInsn(ALOAD, 0); 101 snippet.visitMethodInsn(INVOKEVIRTUAL, "sun/misc/Unsafe", "staticFieldBase", "(Ljava/lang/reflect/Field;)Ljava/lang/Object;", false); 102 snippet.visitVarInsn(ASTORE, 1); 103 104 SubWordTestUtil.getUnsafe(snippet); 105 snippet.visitVarInsn(ALOAD, 0); 106 snippet.visitMethodInsn(INVOKEVIRTUAL, "sun/misc/Unsafe", "staticFieldOffset", "(Ljava/lang/reflect/Field;)J", false); 107 snippet.visitVarInsn(LSTORE, 2); 108 109 SubWordTestUtil.getUnsafe(snippet); 110 snippet.visitVarInsn(ALOAD, 1); 111 snippet.visitVarInsn(LLOAD, 2); 112 snippet.visitLdcInsn(value); 113 snippet.visitMethodInsn(INVOKEVIRTUAL, "sun/misc/Unsafe", "put" + SubWordTestUtil.getUnsafePutMethodName(kind), "(Ljava/lang/Object;J" + kind.getTypeChar() + ")V", false); 114 } else { 115 snippet.visitLdcInsn(value); 116 snippet.visitFieldInsn(PUTSTATIC, internalClassName, fieldName, fieldDescriptor); 117 } 118 119 if (unsafeLoad) { 120 if (!unsafeStore) { 121 snippet.visitLdcInsn(Type.getObjectType(internalClassName)); 122 snippet.visitLdcInsn(fieldName); 123 snippet.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getField", "(Ljava/lang/String;)Ljava/lang/reflect/Field;", false); 124 snippet.visitVarInsn(ASTORE, 0); 125 126 SubWordTestUtil.getUnsafe(snippet); 127 snippet.visitVarInsn(ALOAD, 0); 128 snippet.visitMethodInsn(INVOKEVIRTUAL, "sun/misc/Unsafe", "staticFieldBase", "(Ljava/lang/reflect/Field;)Ljava/lang/Object;", false); 129 snippet.visitVarInsn(ASTORE, 1); 130 131 SubWordTestUtil.getUnsafe(snippet); 132 snippet.visitVarInsn(ALOAD, 0); 133 snippet.visitMethodInsn(INVOKEVIRTUAL, "sun/misc/Unsafe", "staticFieldOffset", "(Ljava/lang/reflect/Field;)J", false); 134 snippet.visitVarInsn(LSTORE, 2); 135 } 136 SubWordTestUtil.getUnsafe(snippet); 137 snippet.visitVarInsn(ALOAD, 1); 138 snippet.visitVarInsn(LLOAD, 2); 139 snippet.visitMethodInsn(INVOKEVIRTUAL, "sun/misc/Unsafe", "get" + SubWordTestUtil.getUnsafePutMethodName(kind), "(Ljava/lang/Object;J)" + kind.getTypeChar(), false); 140 } else { 141 snippet.visitFieldInsn(GETSTATIC, internalClassName, fieldName, fieldDescriptor); 142 } 143 144 snippet.visitLdcInsn(value); 145 SubWordTestUtil.convertToKind(snippet, kind); 146 SubWordTestUtil.testEqual(snippet); 147 148 snippet.visitMaxs(5, 4); 149 snippet.visitEnd(); 150 151 cw.visitEnd(); 152 return cw.toByteArray(); 153 } 154 } 155