# HG changeset patch # User Thomas Wuerthinger # Date 1427734004 -7200 # Node ID 2c86be269fad2bc80e66cef4594aa3fee73395eb # Parent 0b2bd777d9337e818ea09ab9216c9d67dc2020d4# Parent e4bb07ed276ce1b286c1caf27ad8dec8946c51f2 Merge. diff -r 0b2bd777d933 -r 2c86be269fad graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/IncrementDecrementMacroTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/IncrementDecrementMacroTest.java Mon Mar 30 18:46:44 2015 +0200 @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.asm.amd64.test; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; +import static org.junit.Assume.*; + +import java.lang.reflect.*; + +import org.junit.*; + +import com.oracle.graal.amd64.*; +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.asm.test.*; + +public class IncrementDecrementMacroTest extends AssemblerTest { + + @Before + public void checkAMD64() { + assumeTrue("skipping AMD64 specific test", codeCache.getTarget().arch instanceof AMD64); + } + + public static class LongField { + public long x; + + LongField(long x) { + this.x = x; + } + } + + private static class IncrementCodeGenTest implements CodeGenTest { + final int value; + + public IncrementCodeGenTest(int value) { + this.value = value; + } + + @Override + public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { + AMD64MacroAssembler asm = new AMD64MacroAssembler(target, registerConfig); + Register ret = registerConfig.getReturnRegister(Kind.Int); + try { + Field f = LongField.class.getDeclaredField("x"); + AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) unsafe.objectFieldOffset(f)); + asm.incrementq(arg, value); + asm.movq(ret, arg); + asm.ret(0); + return asm.close(true); + } catch (Exception e) { + throw new RuntimeException("exception while trying to generate field access:", e); + } + } + } + + private void assertIncrement(long initValue, int increment) { + assertReturn("longFieldStubIncrement", new IncrementCodeGenTest(increment), initValue + increment, new LongField(initValue)); + } + + private void assertIncrements(int increment) { + assertIncrement(0x4242_4242_4242_4242L, increment); + } + + @SuppressWarnings("unused") + public static long longFieldStubIncrement(LongField arg) { + return 0; + } + + private static class DecrementCodeGenTest implements CodeGenTest { + final int value; + + public DecrementCodeGenTest(int value) { + this.value = value; + } + + @Override + public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { + AMD64MacroAssembler asm = new AMD64MacroAssembler(target, registerConfig); + Register ret = registerConfig.getReturnRegister(Kind.Int); + try { + Field f = LongField.class.getDeclaredField("x"); + AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) unsafe.objectFieldOffset(f)); + asm.decrementq(arg, value); + asm.movq(ret, arg); + asm.ret(0); + return asm.close(true); + } catch (Exception e) { + throw new RuntimeException("exception while trying to generate field access:", e); + } + } + } + + private void assertDecrement(long initValue, int increment) { + assertReturn("longFieldStubDecrement", new DecrementCodeGenTest(increment), initValue - increment, new LongField(initValue)); + } + + private void assertDecrements(int increment) { + assertDecrement(0x4242_4242_4242_4242L, increment); + } + + @SuppressWarnings("unused") + public static long longFieldStubDecrement(LongField arg) { + return 0; + } + + @Test + public void incrementMemTest0() { + int increment = 0; + assertIncrements(increment); + } + + @Test + public void incrementMemTest1() { + int increment = 1; + assertIncrements(increment); + } + + @Test + public void incrementMemTest2() { + int increment = 2; + assertIncrements(increment); + } + + @Test + public void incrementMemTest3() { + int increment = Integer.MAX_VALUE; + assertIncrements(increment); + } + + @Test + public void incrementMemTest4() { + int increment = Integer.MIN_VALUE; + assertIncrements(increment); + } + + @Test + public void incrementMemTest5() { + int increment = -1; + assertIncrements(increment); + } + + @Test + public void incrementMemTest6() { + int increment = -2; + assertIncrements(increment); + } + + @Test + public void incrementMemTest7() { + int increment = -0x1000_0000; + assertIncrements(increment); + } + + @Test + public void decrementMemTest0() { + int decrement = 0; + assertDecrements(decrement); + } + + @Test + public void decrementMemTest1() { + int decrement = 1; + assertDecrements(decrement); + } + + @Test + public void decrementMemTest2() { + int decrement = 2; + assertDecrements(decrement); + } + + @Test + public void decrementMemTest3() { + int decrement = Integer.MAX_VALUE; + assertDecrements(decrement); + } + + @Test + public void decrementMemTest4() { + int decrement = Integer.MIN_VALUE; + assertDecrements(decrement); + } + + @Test + public void decrementMemTest5() { + int decrement = -1; + assertDecrements(decrement); + } + + @Test + public void decrementMemTest6() { + int decrement = -2; + assertDecrements(decrement); + } + + @Test + public void decrementMemTest7() { + int decrement = -0x1000_0000; + assertDecrements(decrement); + } + +} diff -r 0b2bd777d933 -r 2c86be269fad graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java --- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Mon Mar 30 17:57:31 2015 +0200 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Mon Mar 30 18:46:44 2015 +0200 @@ -27,6 +27,7 @@ import static com.oracle.graal.asm.NumUtil.*; import static com.oracle.graal.asm.amd64.AMD64AsmOptions.*; import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.*; +import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64MOp.*; import static com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize.*; import com.oracle.graal.amd64.*; @@ -729,6 +730,7 @@ public static final AMD64MOp DIV = new AMD64MOp("DIV", 0xF7, 6); public static final AMD64MOp IDIV = new AMD64MOp("IDIV", 0xF7, 7); public static final AMD64MOp INC = new AMD64MOp("INC", 0xFF, 0); + public static final AMD64MOp DEC = new AMD64MOp("DEC", 0xFF, 1); // @formatter:on private final int ext; @@ -1961,6 +1963,10 @@ ADD.getMIOpcode(QWORD, isByte(imm32)).emit(this, QWORD, dst, imm32); } + public final void addq(AMD64Address dst, int imm32) { + ADD.getMIOpcode(QWORD, isByte(imm32)).emit(this, QWORD, dst, imm32); + } + public final void addq(Register dst, Register src) { ADD.rmOp.emit(this, QWORD, dst, src); } @@ -2024,6 +2030,10 @@ emitByte(0xC8 | encode); } + public final void decq(AMD64Address dst) { + DEC.emit(this, QWORD, dst); + } + public final void incq(Register dst) { // Don't use it directly. Use Macroincrementq() instead. // Use two-byte form (one-byte from is a REX prefix in 64-bit mode) @@ -2032,6 +2042,10 @@ emitByte(0xC0 | encode); } + public final void incq(AMD64Address dst) { + INC.emit(this, QWORD, dst); + } + public final void movq(Register dst, long imm64) { int encode = prefixqAndEncode(dst.encoding); emitByte(0xB8 | encode); @@ -2130,6 +2144,10 @@ SUB.getMIOpcode(QWORD, isByte(imm32)).emit(this, QWORD, dst, imm32); } + public final void subq(AMD64Address dst, int imm32) { + SUB.getMIOpcode(QWORD, isByte(imm32)).emit(this, QWORD, dst, imm32); + } + public final void subqWide(Register dst, int imm32) { // don't use the sign-extending version, forcing a 32-bit immediate SUB.getMIOpcode(QWORD, false).emit(this, QWORD, dst, imm32); diff -r 0b2bd777d933 -r 2c86be269fad graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java --- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java Mon Mar 30 17:57:31 2015 +0200 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java Mon Mar 30 18:46:44 2015 +0200 @@ -56,6 +56,25 @@ } } + public final void decrementq(AMD64Address dst, int value) { + if (value == Integer.MIN_VALUE) { + subq(dst, value); + return; + } + if (value < 0) { + incrementq(dst, -value); + return; + } + if (value == 0) { + return; + } + if (value == 1 && UseIncDec) { + decq(dst); + } else { + subq(dst, value); + } + } + public void incrementq(Register reg, int value) { if (value == Integer.MIN_VALUE) { addq(reg, value); @@ -75,6 +94,25 @@ } } + public final void incrementq(AMD64Address dst, int value) { + if (value == Integer.MIN_VALUE) { + addq(dst, value); + return; + } + if (value < 0) { + decrementq(dst, -value); + return; + } + if (value == 0) { + return; + } + if (value == 1 && UseIncDec) { + incq(dst); + } else { + addq(dst, value); + } + } + public final void movptr(Register dst, AMD64Address src) { movq(dst, src); } diff -r 0b2bd777d933 -r 2c86be269fad graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java --- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Mon Mar 30 17:57:31 2015 +0200 +++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Mon Mar 30 18:46:44 2015 +0200 @@ -29,6 +29,8 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.phases.util.*; import com.oracle.graal.runtime.*; import com.oracle.graal.test.*; @@ -54,21 +56,25 @@ protected InstalledCode assembleMethod(Method m, CodeGenTest test) { ResolvedJavaMethod method = getMetaAccess().lookupJavaMethod(m); - RegisterConfig registerConfig = codeCache.getRegisterConfig(); - CallingConvention cc = CodeUtil.getCallingConvention(codeCache, CallingConvention.Type.JavaCallee, method, false); + try (Scope s = Debug.scope("assembleMethod", method, codeCache)) { + RegisterConfig registerConfig = codeCache.getRegisterConfig(); + CallingConvention cc = CodeUtil.getCallingConvention(codeCache, CallingConvention.Type.JavaCallee, method, false); - CompilationResult compResult = new CompilationResult(); - byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc); - compResult.setTargetCode(targetCode, targetCode.length); + CompilationResult compResult = new CompilationResult(); + byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc); + compResult.setTargetCode(targetCode, targetCode.length); + + InstalledCode code = codeCache.addMethod(method, compResult, null, null); - InstalledCode code = codeCache.addMethod(method, compResult, null, null); - - DisassemblerProvider dis = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getDisassembler(); - if (dis != null) { - String disasm = dis.disassemble(code); - Assert.assertTrue(code.toString(), disasm == null || disasm.length() > 0); + DisassemblerProvider dis = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getDisassembler(); + if (dis != null) { + String disasm = dis.disassemble(code); + Assert.assertTrue(code.toString(), disasm == null || disasm.length() > 0); + } + return code; + } catch (Throwable e) { + throw Debug.handle(e); } - return code; } protected Object runTest(String methodName, CodeGenTest test, Object... args) { diff -r 0b2bd777d933 -r 2c86be269fad graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCounterOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCounterOp.java Mon Mar 30 17:57:31 2015 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCounterOp.java Mon Mar 30 18:46:44 2015 +0200 @@ -24,10 +24,6 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.api.code.ValueUtil.*; -import static com.oracle.graal.asm.NumUtil.*; -import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.*; -import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64MOp.*; -import static com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize.*; import static com.oracle.graal.compiler.common.GraalInternalError.*; import com.oracle.graal.api.code.*; @@ -107,11 +103,7 @@ // increment counter (in memory) if (isConstant(incrementValue)) { int increment = asInt(asConstant(incrementValue)); - if (increment == 1) { - INC.emit(masm, QWORD, counterAddr); - } else { - ADD.getMIOpcode(QWORD, isByte(increment)).emit(masm, QWORD, counterAddr, increment); - } + masm.incrementq(counterAddr, increment); } else { masm.addq(counterAddr, asRegister(incrementValue)); }