1 /* 2 * Copyright (c) 2015, 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.asm.amd64.test; 26 27 import static jdk.vm.ci.code.ValueUtil.asRegister; 28 import static org.junit.Assume.assumeTrue; 29 30 import java.lang.reflect.Field; 31 32 import jdk.vm.ci.amd64.AMD64; 33 import jdk.vm.ci.code.CallingConvention; 34 import jdk.vm.ci.code.Register; 35 import jdk.vm.ci.code.RegisterConfig; 36 import jdk.vm.ci.code.TargetDescription; 37 import jdk.vm.ci.meta.JavaKind; 38 39 import org.junit.Before; 40 import org.junit.Test; 41 42 import org.graalvm.compiler.asm.amd64.AMD64Address; 43 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; 44 import org.graalvm.compiler.asm.test.AssemblerTest; 45 import org.graalvm.compiler.code.CompilationResult; 46 47 public class IncrementDecrementMacroTest extends AssemblerTest { 48 49 @Before 50 public void checkAMD64() { 51 assumeTrue("skipping AMD64 specific test", codeCache.getTarget().arch instanceof AMD64); 52 } 53 54 public static class LongField { 55 public long x; 56 57 LongField(long x) { 58 this.x = x; 59 } 60 } 61 62 private static class IncrementCodeGenTest implements CodeGenTest { 63 final int value; 64 65 IncrementCodeGenTest(int value) { 66 this.value = value; 67 } 68 69 @Override 70 public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 71 AMD64MacroAssembler asm = new AMD64MacroAssembler(target); 72 Register ret = registerConfig.getReturnRegister(JavaKind.Int); 73 try { 74 Field f = LongField.class.getDeclaredField("x"); 75 AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) UNSAFE.objectFieldOffset(f)); 76 asm.incrementq(arg, value); 77 asm.movq(ret, arg); 78 asm.ret(0); 79 return asm.close(true); 80 } catch (Exception e) { 81 throw new RuntimeException("exception while trying to generate field access:", e); 82 } 83 } 84 } 85 86 private void assertIncrement(long initValue, int increment) { 87 assertReturn("longFieldStubIncrement", new IncrementCodeGenTest(increment), initValue + increment, new LongField(initValue)); 88 } 89 90 private void assertIncrements(int increment) { 91 assertIncrement(0x4242_4242_4242_4242L, increment); 92 } 93 94 @SuppressWarnings("unused") 95 public static long longFieldStubIncrement(LongField arg) { 96 return 0; 97 } 98 99 private static class DecrementCodeGenTest implements CodeGenTest { 100 final int value; 101 102 DecrementCodeGenTest(int value) { 103 this.value = value; 104 } 105 106 @Override 107 public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 108 AMD64MacroAssembler asm = new AMD64MacroAssembler(target); 109 Register ret = registerConfig.getReturnRegister(JavaKind.Int); 110 try { 111 Field f = LongField.class.getDeclaredField("x"); 112 AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) UNSAFE.objectFieldOffset(f)); 113 asm.decrementq(arg, value); 114 asm.movq(ret, arg); 115 asm.ret(0); 116 return asm.close(true); 117 } catch (Exception e) { 118 throw new RuntimeException("exception while trying to generate field access:", e); 119 } 120 } 121 } 122 123 private void assertDecrement(long initValue, int increment) { 124 assertReturn("longFieldStubDecrement", new DecrementCodeGenTest(increment), initValue - increment, new LongField(initValue)); 125 } 126 127 private void assertDecrements(int increment) { 128 assertDecrement(0x4242_4242_4242_4242L, increment); 129 } 130 131 @SuppressWarnings("unused") 132 public static long longFieldStubDecrement(LongField arg) { 133 return 0; 134 } 135 136 @Test 137 public void incrementMemTest0() { 138 int increment = 0; 139 assertIncrements(increment); 140 } 141 142 @Test 143 public void incrementMemTest1() { 144 int increment = 1; 145 assertIncrements(increment); 146 } 147 148 @Test 149 public void incrementMemTest2() { 150 int increment = 2; 151 assertIncrements(increment); 152 } 153 154 @Test 155 public void incrementMemTest3() { 156 int increment = Integer.MAX_VALUE; 157 assertIncrements(increment); 158 } 159 160 @Test 161 public void incrementMemTest4() { 162 int increment = Integer.MIN_VALUE; 163 assertIncrements(increment); 164 } 165 166 @Test 167 public void incrementMemTest5() { 168 int increment = -1; 169 assertIncrements(increment); 170 } 171 172 @Test 173 public void incrementMemTest6() { 174 int increment = -2; 175 assertIncrements(increment); 176 } 177 178 @Test 179 public void incrementMemTest7() { 180 int increment = -0x1000_0000; 181 assertIncrements(increment); 182 } 183 184 @Test 185 public void decrementMemTest0() { 186 int decrement = 0; 187 assertDecrements(decrement); 188 } 189 190 @Test 191 public void decrementMemTest1() { 192 int decrement = 1; 193 assertDecrements(decrement); 194 } 195 196 @Test 197 public void decrementMemTest2() { 198 int decrement = 2; 199 assertDecrements(decrement); 200 } 201 202 @Test 203 public void decrementMemTest3() { 204 int decrement = Integer.MAX_VALUE; 205 assertDecrements(decrement); 206 } 207 208 @Test 209 public void decrementMemTest4() { 210 int decrement = Integer.MIN_VALUE; 211 assertDecrements(decrement); 212 } 213 214 @Test 215 public void decrementMemTest5() { 216 int decrement = -1; 217 assertDecrements(decrement); 218 } 219 220 @Test 221 public void decrementMemTest6() { 222 int decrement = -2; 223 assertDecrements(decrement); 224 } 225 226 @Test 227 public void decrementMemTest7() { 228 int decrement = -0x1000_0000; 229 assertDecrements(decrement); 230 } 231 232 }