--- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp Fri Dec 18 15:29:43 2015 -0800
+++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp Tue Dec 15 16:55:24 2015 +0100
@@ -179,7 +179,7 @@
nonstatic_field(Method, _access_flags, AccessFlags) \
nonstatic_field(Method, _vtable_index, int) \
nonstatic_field(Method, _intrinsic_id, u2) \
- nonstatic_field(Method, _flags, u1) \
+ nonstatic_field(Method, _flags, u2) \
volatile_nonstatic_field(Method, _code, nmethod*) \
volatile_nonstatic_field(Method, _from_compiled_entry, address) \
\
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/code/CodeInstallationTest.java Tue Dec 15 16:55:24 2015 +0100
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 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 compiler.jvmci.code;
+
+import java.lang.reflect.Method;
+
+import jdk.vm.ci.amd64.AMD64;
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.CodeCacheProvider;
+import jdk.vm.ci.code.CompilationResult;
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.runtime.JVMCI;
+import jdk.vm.ci.runtime.JVMCIBackend;
+import jdk.vm.ci.sparc.SPARC;
+
+import org.junit.Assert;
+
+import compiler.jvmci.code.amd64.AMD64TestAssembler;
+import compiler.jvmci.code.sparc.SPARCTestAssembler;
+
+/**
+ * Base class for code installation tests.
+ */
+public class CodeInstallationTest {
+
+ protected final MetaAccessProvider metaAccess;
+ protected final CodeCacheProvider codeCache;
+ protected final TargetDescription target;
+ protected final ConstantReflectionProvider constantReflection;
+
+ public CodeInstallationTest() {
+ JVMCIBackend backend = JVMCI.getRuntime().getHostJVMCIBackend();
+ metaAccess = backend.getMetaAccess();
+ codeCache = backend.getCodeCache();
+ target = backend.getTarget();
+ constantReflection = backend.getConstantReflection();
+ }
+
+ protected interface TestCompiler {
+
+ void compile(TestAssembler asm);
+ }
+
+ private TestAssembler createAssembler(CompilationResult result) {
+ Architecture arch = codeCache.getTarget().arch;
+ if (arch instanceof AMD64) {
+ return new AMD64TestAssembler(result, codeCache);
+ } else if (arch instanceof SPARC) {
+ return new SPARCTestAssembler(result, codeCache);
+ } else {
+ Assert.fail("unsupported architecture");
+ return null;
+ }
+ }
+
+ protected Method getMethod(String name, Class<?>... args) {
+ try {
+ return getClass().getMethod(name, args);
+ } catch (NoSuchMethodException e) {
+ Assert.fail("method not found");
+ return null;
+ }
+ }
+
+ protected void test(TestCompiler compiler, Method method, Object... args) {
+ CompilationResult result = new CompilationResult(method.getName());
+ TestAssembler asm = createAssembler(result);
+
+ asm.emitPrologue();
+ compiler.compile(asm);
+ asm.finish();
+
+ result.close();
+
+ ResolvedJavaMethod resolvedMethod = metaAccess.lookupJavaMethod(method);
+ InstalledCode installed = codeCache.addCode(resolvedMethod, result, null, null);
+
+ try {
+ Object expected = method.invoke(null, args);
+ Object actual = installed.executeVarargs(args);
+ Assert.assertEquals(expected, actual);
+ } catch (Exception e) {
+ e.printStackTrace();
+ Assert.fail(e.toString());
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/code/DataPatchTest.java Tue Dec 15 16:55:24 2015 +0100
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * @test
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @compile CodeInstallationTest.java TestAssembler.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.code.DataPatchTest
+ */
+
+package compiler.jvmci.code;
+
+import jdk.vm.ci.code.CompilationResult.DataSectionReference;
+import jdk.vm.ci.code.DataSection.Data;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.hotspot.HotSpotConstant;
+import jdk.vm.ci.hotspot.HotSpotVMConfig;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+import org.junit.Assume;
+import org.junit.Test;
+
+/**
+ * Test code installation with data patches.
+ */
+public class DataPatchTest extends CodeInstallationTest {
+
+ public static Class<?> getConstClass() {
+ return DataPatchTest.class;
+ }
+
+ private void test(TestCompiler compiler) {
+ test(compiler, getMethod("getConstClass"));
+ }
+
+
+ @Test
+ public void testInlineObject() {
+ test(asm -> {
+ ResolvedJavaType type = metaAccess.lookupJavaType(getConstClass());
+ HotSpotConstant c = (HotSpotConstant) type.getJavaClass();
+ Register ret = asm.emitLoadPointer(c);
+ asm.emitPointerRet(ret);
+ });
+ }
+
+ @Test
+ public void testInlineNarrowObject() {
+ Assume.assumeTrue(HotSpotVMConfig.config().useCompressedOops);
+ test(asm -> {
+ ResolvedJavaType type = metaAccess.lookupJavaType(getConstClass());
+ HotSpotConstant c = (HotSpotConstant) type.getJavaClass();
+ Register compressed = asm.emitLoadPointer((HotSpotConstant) c.compress());
+ Register ret = asm.emitUncompressPointer(compressed, HotSpotVMConfig.config().narrowOopBase, HotSpotVMConfig.config().narrowOopShift);
+ asm.emitPointerRet(ret);
+ });
+ }
+
+ @Test
+ public void testDataSectionReference() {
+ test(asm -> {
+ ResolvedJavaType type = metaAccess.lookupJavaType(getConstClass());
+ HotSpotConstant c = (HotSpotConstant) type.getJavaClass();
+ Data data = codeCache.createDataItem(c);
+ DataSectionReference ref = asm.result.getDataSection().insertData(data);
+ Register ret = asm.emitLoadPointer(ref);
+ asm.emitPointerRet(ret);
+ });
+ }
+
+ @Test
+ public void testNarrowDataSectionReference() {
+ Assume.assumeTrue(HotSpotVMConfig.config().useCompressedOops);
+ test(asm -> {
+ ResolvedJavaType type = metaAccess.lookupJavaType(getConstClass());
+ HotSpotConstant c = (HotSpotConstant) type.getJavaClass();
+ HotSpotConstant cCompressed = (HotSpotConstant) c.compress();
+ Data data = codeCache.createDataItem(cCompressed);
+ DataSectionReference ref = asm.result.getDataSection().insertData(data);
+ Register compressed = asm.emitLoadNarrowPointer(ref);
+ Register ret = asm.emitUncompressPointer(compressed, HotSpotVMConfig.config().narrowOopBase, HotSpotVMConfig.config().narrowOopShift);
+ asm.emitPointerRet(ret);
+ });
+ }
+
+ @Test
+ public void testInlineMetadata() {
+ test(asm -> {
+ ResolvedJavaType type = metaAccess.lookupJavaType(getConstClass());
+ Register klass = asm.emitLoadPointer((HotSpotConstant) type.getObjectHub());
+ Register ret = asm.emitLoadPointer(klass, HotSpotVMConfig.config().classMirrorOffset);
+ asm.emitPointerRet(ret);
+ });
+ }
+
+ @Test
+ public void testInlineNarrowMetadata() {
+ Assume.assumeTrue(HotSpotVMConfig.config().useCompressedClassPointers);
+ test(asm -> {
+ ResolvedJavaType type = metaAccess.lookupJavaType(getConstClass());
+ HotSpotConstant hub = (HotSpotConstant) type.getObjectHub();
+ Register narrowKlass = asm.emitLoadPointer((HotSpotConstant) hub.compress());
+ Register klass = asm.emitUncompressPointer(narrowKlass, HotSpotVMConfig.config().narrowKlassBase, HotSpotVMConfig.config().narrowKlassShift);
+ Register ret = asm.emitLoadPointer(klass, HotSpotVMConfig.config().classMirrorOffset);
+ asm.emitPointerRet(ret);
+ });
+ }
+
+ @Test
+ public void testMetadataInDataSection() {
+ test(asm -> {
+ ResolvedJavaType type = metaAccess.lookupJavaType(getConstClass());
+ HotSpotConstant hub = (HotSpotConstant) type.getObjectHub();
+ Data data = codeCache.createDataItem(hub);
+ DataSectionReference ref = asm.result.getDataSection().insertData(data);
+ Register klass = asm.emitLoadPointer(ref);
+ Register ret = asm.emitLoadPointer(klass, HotSpotVMConfig.config().classMirrorOffset);
+ asm.emitPointerRet(ret);
+ });
+ }
+
+ @Test
+ public void testNarrowMetadataInDataSection() {
+ Assume.assumeTrue(HotSpotVMConfig.config().useCompressedClassPointers);
+ test(asm -> {
+ ResolvedJavaType type = metaAccess.lookupJavaType(getConstClass());
+ HotSpotConstant hub = (HotSpotConstant) type.getObjectHub();
+ HotSpotConstant narrowHub = (HotSpotConstant) hub.compress();
+ Data data = codeCache.createDataItem(narrowHub);
+ DataSectionReference ref = asm.result.getDataSection().insertData(data);
+ Register narrowKlass = asm.emitLoadNarrowPointer(ref);
+ Register klass = asm.emitUncompressPointer(narrowKlass, HotSpotVMConfig.config().narrowKlassBase, HotSpotVMConfig.config().narrowKlassShift);
+ Register ret = asm.emitLoadPointer(klass, HotSpotVMConfig.config().classMirrorOffset);
+ asm.emitPointerRet(ret);
+ });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/code/DebugInfoTest.java Tue Dec 15 16:55:24 2015 +0100
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 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 compiler.jvmci.code;
+
+import java.lang.reflect.Method;
+
+import jdk.vm.ci.code.BytecodeFrame;
+import jdk.vm.ci.code.DebugInfo;
+import jdk.vm.ci.code.Location;
+import jdk.vm.ci.code.VirtualObject;
+import jdk.vm.ci.hotspot.HotSpotReferenceMap;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaValue;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+/**
+ * Test code installation with debug information.
+ */
+public class DebugInfoTest extends CodeInstallationTest {
+
+ protected interface DebugInfoCompiler {
+
+ VirtualObject[] compile(TestAssembler asm, JavaValue[] frameValues);
+ }
+
+ protected void test(DebugInfoCompiler compiler, Method method, int bci, JavaKind... slotKinds) {
+ ResolvedJavaMethod resolvedMethod = metaAccess.lookupJavaMethod(method);
+
+ int numLocals = resolvedMethod.getMaxLocals();
+ int numStack = slotKinds.length - numLocals;
+ JavaValue[] values = new JavaValue[slotKinds.length];
+ test(asm -> {
+ VirtualObject[] vobjs = compiler.compile(asm, values);
+
+ BytecodeFrame frame = new BytecodeFrame(null, resolvedMethod, bci, false, false, values, slotKinds, numLocals, numStack, 0);
+ DebugInfo info = new DebugInfo(frame, vobjs);
+ info.setReferenceMap(new HotSpotReferenceMap(new Location[0], new Location[0], new int[0], 8));
+
+ asm.emitTrap(info);
+ }, method);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/code/SimpleCodeInstallationTest.java Tue Dec 15 16:55:24 2015 +0100
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * @test
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @compile CodeInstallationTest.java TestAssembler.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.code.SimpleCodeInstallationTest
+ */
+
+package compiler.jvmci.code;
+
+import jdk.vm.ci.code.Register;
+
+import org.junit.Test;
+
+/**
+ * Test simple code installation.
+ */
+public class SimpleCodeInstallationTest extends CodeInstallationTest {
+
+ public static int add(int a, int b) {
+ return a + b;
+ }
+
+ private static void compileAdd(TestAssembler asm) {
+ Register arg0 = asm.emitIntArg0();
+ Register arg1 = asm.emitIntArg1();
+ Register ret = asm.emitIntAdd(arg0, arg1);
+ asm.emitIntRet(ret);
+ }
+
+ @Test
+ public void test() {
+ test(SimpleCodeInstallationTest::compileAdd, getMethod("add", int.class, int.class), 5, 7);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/code/SimpleDebugInfoTest.java Tue Dec 15 16:55:24 2015 +0100
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * @test
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.code.SimpleDebugInfoTest
+ */
+
+package compiler.jvmci.code;
+
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.hotspot.HotSpotConstant;
+import jdk.vm.ci.hotspot.HotSpotVMConfig;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.Value;
+
+import org.junit.Assume;
+import org.junit.Test;
+
+public class SimpleDebugInfoTest extends DebugInfoTest {
+
+ public static int intOnStack() {
+ return 42;
+ }
+
+ private void testIntOnStack(DebugInfoCompiler compiler) {
+ test(compiler, getMethod("intOnStack"), 2, JavaKind.Int);
+ }
+
+ public static int intInLocal() {
+ int local = 42;
+ return local;
+ }
+
+ public void testIntInLocal(DebugInfoCompiler compiler) {
+ test(compiler, getMethod("intInLocal"), 3, JavaKind.Int);
+ }
+
+ @Test
+ public void testConstInt() {
+ DebugInfoCompiler compiler = (asm, values) -> {
+ values[0] = JavaConstant.forInt(42);
+ return null;
+ };
+ testIntOnStack(compiler);
+ testIntInLocal(compiler);
+ }
+
+ @Test
+ public void testRegInt() {
+ DebugInfoCompiler compiler = (asm, values) -> {
+ Register reg = asm.emitLoadInt(42);
+ values[0] = reg.asValue(target.getLIRKind(JavaKind.Int));
+ return null;
+ };
+ testIntOnStack(compiler);
+ testIntInLocal(compiler);
+ }
+
+ @Test
+ public void testStackInt() {
+ DebugInfoCompiler compiler = (asm, values) -> {
+ Register reg = asm.emitLoadInt(42);
+ values[0] = asm.emitIntToStack(reg);
+ return null;
+ };
+ testIntOnStack(compiler);
+ testIntInLocal(compiler);
+ }
+
+
+ public static float floatOnStack() {
+ return 42.0f;
+ }
+
+ private void testFloatOnStack(DebugInfoCompiler compiler) {
+ test(compiler, getMethod("floatOnStack"), 2, JavaKind.Float);
+ }
+
+ public static float floatInLocal() {
+ float local = 42.0f;
+ return local;
+ }
+
+ private void testFloatInLocal(DebugInfoCompiler compiler) {
+ test(compiler, getMethod("floatInLocal"), 3, JavaKind.Float);
+ }
+
+ @Test
+ public void testConstFloat() {
+ DebugInfoCompiler compiler = (asm, values) -> {
+ values[0] = JavaConstant.forFloat(42.0f);
+ return null;
+ };
+ testFloatOnStack(compiler);
+ testFloatInLocal(compiler);
+ }
+
+ @Test
+ public void testRegFloat() {
+ DebugInfoCompiler compiler = (asm, values) -> {
+ Register reg = asm.emitLoadFloat(42.0f);
+ values[0] = reg.asValue(target.getLIRKind(JavaKind.Float));
+ return null;
+ };
+ testFloatOnStack(compiler);
+ testFloatInLocal(compiler);
+ }
+
+ @Test
+ public void testStackFloat() {
+ DebugInfoCompiler compiler = (asm, values) -> {
+ Register reg = asm.emitLoadFloat(42.0f);
+ values[0] = asm.emitFloatToStack(reg);
+ return null;
+ };
+ testFloatOnStack(compiler);
+ testFloatInLocal(compiler);
+ }
+
+
+ public static long longOnStack() {
+ return 42;
+ }
+
+ private void testLongOnStack(DebugInfoCompiler compiler) {
+ test(compiler, getMethod("longOnStack"), 3, JavaKind.Long, JavaKind.Illegal);
+ }
+
+ public static long longInLocal() {
+ long local = 42;
+ return local;
+ }
+
+ private void testLongInLocal(DebugInfoCompiler compiler) {
+ test(compiler, getMethod("longInLocal"), 4, JavaKind.Long, JavaKind.Illegal);
+ }
+
+ @Test
+ public void testConstLong() {
+ DebugInfoCompiler compiler = (asm, values) -> {
+ values[0] = JavaConstant.forLong(42);
+ values[1] = Value.ILLEGAL;
+ return null;
+ };
+ testLongOnStack(compiler);
+ testLongInLocal(compiler);
+ }
+
+ @Test
+ public void testRegLong() {
+ DebugInfoCompiler compiler = (asm, values) -> {
+ Register reg = asm.emitLoadLong(42);
+ values[0] = reg.asValue(target.getLIRKind(JavaKind.Long));
+ values[1] = Value.ILLEGAL;
+ return null;
+ };
+ testLongOnStack(compiler);
+ testLongInLocal(compiler);
+ }
+
+ @Test
+ public void testStackLong() {
+ DebugInfoCompiler compiler = (asm, values) -> {
+ Register reg = asm.emitLoadLong(42);
+ values[0] = asm.emitLongToStack(reg);
+ values[1] = Value.ILLEGAL;
+ return null;
+ };
+ testLongOnStack(compiler);
+ testLongInLocal(compiler);
+ }
+
+
+ public static Class<?> objectOnStack() {
+ return SimpleDebugInfoTest.class;
+ }
+
+ private void testObjectOnStack(DebugInfoCompiler compiler) {
+ test(compiler, getMethod("objectOnStack"), 2, JavaKind.Object);
+ }
+
+ public static Class<?> objectInLocal() {
+ Class<?> local = SimpleDebugInfoTest.class;
+ return local;
+ }
+
+ private void testObjectInLocal(DebugInfoCompiler compiler) {
+ test(compiler, getMethod("objectInLocal"), 3, JavaKind.Object);
+ }
+
+ @Test
+ public void testConstObject() {
+ ResolvedJavaType type = metaAccess.lookupJavaType(objectOnStack());
+ DebugInfoCompiler compiler = (asm, values) -> {
+ values[0] = type.getJavaClass();
+ return null;
+ };
+ testObjectOnStack(compiler);
+ testObjectInLocal(compiler);
+ }
+
+ @Test
+ public void testRegObject() {
+ ResolvedJavaType type = metaAccess.lookupJavaType(objectOnStack());
+ DebugInfoCompiler compiler = (asm, values) -> {
+ Register reg = asm.emitLoadPointer((HotSpotConstant) type.getJavaClass());
+ values[0] = reg.asValue(target.getLIRKind(JavaKind.Object));
+ return null;
+ };
+ testObjectOnStack(compiler);
+ testObjectInLocal(compiler);
+ }
+
+ @Test
+ public void testStackObject() {
+ ResolvedJavaType type = metaAccess.lookupJavaType(objectOnStack());
+ DebugInfoCompiler compiler = (asm, values) -> {
+ Register reg = asm.emitLoadPointer((HotSpotConstant) type.getJavaClass());
+ values[0] = asm.emitPointerToStack(reg);
+ return null;
+ };
+ testObjectOnStack(compiler);
+ testObjectInLocal(compiler);
+ }
+
+ @Test
+ public void testRegNarrowObject() {
+ Assume.assumeTrue(HotSpotVMConfig.config().useCompressedOops);
+ ResolvedJavaType type = metaAccess.lookupJavaType(objectOnStack());
+ DebugInfoCompiler compiler = (asm, values) -> {
+ HotSpotConstant wide = (HotSpotConstant) type.getJavaClass();
+ Register reg = asm.emitLoadPointer((HotSpotConstant) wide.compress());
+ values[0] = reg.asValue(asm.narrowOopKind);
+ return null;
+ };
+ testObjectOnStack(compiler);
+ testObjectInLocal(compiler);
+ }
+
+ @Test
+ public void testStackNarrowObject() {
+ Assume.assumeTrue(HotSpotVMConfig.config().useCompressedOops);
+ ResolvedJavaType type = metaAccess.lookupJavaType(objectOnStack());
+ DebugInfoCompiler compiler = (asm, values) -> {
+ HotSpotConstant wide = (HotSpotConstant) type.getJavaClass();
+ Register reg = asm.emitLoadPointer((HotSpotConstant) wide.compress());
+ values[0] = asm.emitNarrowPointerToStack(reg);
+ return null;
+ };
+ testObjectOnStack(compiler);
+ testObjectInLocal(compiler);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/code/TestAssembler.java Tue Dec 15 16:55:24 2015 +0100
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 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 compiler.jvmci.code;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+
+import jdk.vm.ci.code.CodeCacheProvider;
+import jdk.vm.ci.code.CompilationResult;
+import jdk.vm.ci.code.CompilationResult.DataSectionReference;
+import jdk.vm.ci.code.DebugInfo;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.StackSlot;
+import jdk.vm.ci.hotspot.HotSpotConstant;
+import jdk.vm.ci.meta.LIRKind;
+import jdk.vm.ci.meta.PlatformKind;
+
+/**
+ * Simple assembler used by the code installation tests.
+ */
+public abstract class TestAssembler {
+
+ /**
+ * Emit the method prologue code (e.g. building the new stack frame).
+ */
+ public abstract void emitPrologue();
+
+ /**
+ * Emit code to grow the stack frame.
+ * @param size the size in bytes that the stack should grow
+ */
+ public abstract void emitGrowStack(int size);
+
+ /**
+ * Get the register containing the first 32-bit integer argument.
+ */
+ public abstract Register emitIntArg0();
+
+ /**
+ * Get the register containing the second 32-bit integer argument.
+ */
+ public abstract Register emitIntArg1();
+
+ /**
+ * Emit code to add two 32-bit integer registers. May reuse one of the argument registers.
+ */
+ public abstract Register emitIntAdd(Register a, Register b);
+
+ /**
+ * Emit code to load a constant 32-bit integer to a register.
+ */
+ public abstract Register emitLoadInt(int value);
+
+ /**
+ * Emit code to load a constant 64-bit integer to a register.
+ */
+ public abstract Register emitLoadLong(long value);
+
+ /**
+ * Emit code to load a constant single-precision float to a register.
+ */
+ public abstract Register emitLoadFloat(float value);
+
+ /**
+ * Emit code to load a constant oop or metaspace pointer to a register.
+ * The pointer may be wide or narrow, depending on {@link HotSpotConstant#isCompressed() c.isCompressed()}.
+ */
+ public abstract Register emitLoadPointer(HotSpotConstant c);
+
+ /**
+ * Emit code to load a wide pointer from the {@link DataSection} to a register.
+ */
+ public abstract Register emitLoadPointer(DataSectionReference ref);
+
+ /**
+ * Emit code to load a narrow pointer from the {@link DataSection} to a register.
+ */
+ public abstract Register emitLoadNarrowPointer(DataSectionReference ref);
+
+ /**
+ * Emit code to load a (wide) pointer from a memory location to a register.
+ */
+ public abstract Register emitLoadPointer(Register base, int offset);
+
+ /**
+ * Emit code to store a 32-bit integer from a register to a new stack slot.
+ */
+ public abstract StackSlot emitIntToStack(Register a);
+
+ /**
+ * Emit code to store a 64-bit integer from a register to a new stack slot.
+ */
+ public abstract StackSlot emitLongToStack(Register a);
+
+ /**
+ * Emit code to store a single-precision float from a register to a new stack slot.
+ */
+ public abstract StackSlot emitFloatToStack(Register a);
+
+ /**
+ * Emit code to store a wide pointer from a register to a new stack slot.
+ */
+ public abstract StackSlot emitPointerToStack(Register a);
+
+ /**
+ * Emit code to store a narrow pointer from a register to a new stack slot.
+ */
+ public abstract StackSlot emitNarrowPointerToStack(Register a);
+
+ /**
+ * Emit code to uncompress a narrow pointer. The input pointer is guaranteed to be non-null.
+ */
+ public abstract Register emitUncompressPointer(Register compressed, long base, int shift);
+
+ /**
+ * Emit code to return from a function, returning a 32-bit integer.
+ */
+ public abstract void emitIntRet(Register a);
+
+ /**
+ * Emit code to return from a function, returning a wide oop pointer.
+ */
+ public abstract void emitPointerRet(Register a);
+
+ /**
+ * Emit code that traps, forcing a deoptimization.
+ */
+ public abstract void emitTrap(DebugInfo info);
+
+ protected int position() {
+ return data.position();
+ }
+
+ public final CompilationResult result;
+ public final LIRKind narrowOopKind;
+
+ private ByteBuffer data;
+ protected final CodeCacheProvider codeCache;
+
+ private final Register[] registers;
+ private int nextRegister;
+
+ protected int frameSize;
+ private int stackAlignment;
+ private int curStackSlot;
+
+ protected TestAssembler(CompilationResult result, CodeCacheProvider codeCache, int initialFrameSize, int stackAlignment, PlatformKind narrowOopKind, Register... registers) {
+ this.result = result;
+ this.narrowOopKind = LIRKind.reference(narrowOopKind);
+
+ this.data = ByteBuffer.allocate(32).order(ByteOrder.nativeOrder());
+ this.codeCache = codeCache;
+
+ this.registers = registers;
+ this.nextRegister = 0;
+
+ this.frameSize = initialFrameSize;
+ this.stackAlignment = stackAlignment;
+ this.curStackSlot = initialFrameSize;
+ }
+
+ protected Register newRegister() {
+ return registers[nextRegister++];
+ }
+
+ protected StackSlot newStackSlot(LIRKind kind) {
+ curStackSlot += kind.getPlatformKind().getSizeInBytes();
+ if (curStackSlot > frameSize) {
+ int newFrameSize = curStackSlot;
+ if (newFrameSize % stackAlignment != 0) {
+ newFrameSize += stackAlignment - (newFrameSize % stackAlignment);
+ }
+ emitGrowStack(newFrameSize - frameSize);
+ frameSize = newFrameSize;
+ }
+ return StackSlot.get(kind, -curStackSlot, true);
+ }
+
+ public void finish() {
+ result.setTotalFrameSize(frameSize);
+ result.setTargetCode(data.array(), data.position());
+ }
+
+ private void ensureSize(int length) {
+ if (length >= data.limit()) {
+ byte[] newBuf = Arrays.copyOf(data.array(), length * 4);
+ ByteBuffer newData = ByteBuffer.wrap(newBuf);
+ newData.order(data.order());
+ newData.position(data.position());
+ data = newData;
+ }
+ }
+
+ protected void emitByte(int b) {
+ ensureSize(data.position() + 1);
+ data.put((byte) (b & 0xFF));
+ }
+
+ protected void emitShort(int b) {
+ ensureSize(data.position() + 2);
+ data.putShort((short) b);
+ }
+
+ protected void emitInt(int b) {
+ ensureSize(data.position() + 4);
+ data.putInt(b);
+ }
+
+ protected void emitLong(long b) {
+ ensureSize(data.position() + 8);
+ data.putLong(b);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/code/VirtualObjectDebugInfoTest.java Tue Dec 15 16:55:24 2015 +0100
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * @test
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.code.VirtualObjectDebugInfoTest
+ */
+
+package compiler.jvmci.code;
+
+import java.util.ArrayList;
+import java.util.Objects;
+
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.VirtualObject;
+import jdk.vm.ci.hotspot.HotSpotConstant;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaValue;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class VirtualObjectDebugInfoTest extends DebugInfoTest {
+
+ private static class TestClass {
+
+ private long longField;
+ private int intField;
+ private float floatField;
+ private Object[] arrayField;
+
+ public TestClass() {
+ this.longField = 8472;
+ this.intField = 42;
+ this.floatField = 3.14f;
+ this.arrayField = new Object[] { Integer.valueOf(58), this, null, Integer.valueOf(17), "Hello, World!" };
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof TestClass)) {
+ return false;
+ }
+
+ TestClass other = (TestClass) o;
+ if (this.longField != other.longField
+ || this.intField != other.intField
+ || this.floatField != other.floatField
+ || this.arrayField.length != other.arrayField.length) {
+ return false;
+ }
+
+ for (int i = 0; i < this.arrayField.length; i++) {
+ // break cycle
+ if (this.arrayField[i] == this && other.arrayField[i] == other) {
+ continue;
+ }
+
+ if (!Objects.equals(this.arrayField[i], other.arrayField[i])) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ public static TestClass buildObject() {
+ return new TestClass();
+ }
+
+ private VirtualObject[] compileBuildObject(TestAssembler asm, JavaValue[] values) {
+ TestClass template = new TestClass();
+ ArrayList<VirtualObject> vobjs = new ArrayList<>();
+
+ ResolvedJavaType retType = metaAccess.lookupJavaType(TestClass.class);
+ VirtualObject ret = VirtualObject.get(retType, vobjs.size());
+ vobjs.add(ret);
+ values[0] = ret;
+
+ ResolvedJavaType arrayType = metaAccess.lookupJavaType(Object[].class);
+ VirtualObject array = VirtualObject.get(arrayType, vobjs.size());
+ vobjs.add(array);
+
+ // build array for ret.arrayField
+ ResolvedJavaType integerType = metaAccess.lookupJavaType(Integer.class);
+ JavaValue[] arrayContent = new JavaValue[template.arrayField.length];
+ JavaKind[] arrayKind = new JavaKind[template.arrayField.length];
+ for (int i = 0; i < arrayContent.length; i++) {
+ arrayKind[i] = JavaKind.Object;
+ if (template.arrayField[i] == null) {
+ arrayContent[i] = JavaConstant.NULL_POINTER;
+ } else if (template.arrayField[i] == template) {
+ arrayContent[i] = ret;
+ } else if (template.arrayField[i] instanceof Integer) {
+ int value = (Integer) template.arrayField[i];
+ VirtualObject boxed = VirtualObject.get(integerType, vobjs.size());
+ vobjs.add(boxed);
+ arrayContent[i] = boxed;
+ boxed.setValues(new JavaValue[]{JavaConstant.forInt(value)}, new JavaKind[]{JavaKind.Int});
+ } else if (template.arrayField[i] instanceof String) {
+ String value = (String) template.arrayField[i];
+ Register reg = asm.emitLoadPointer((HotSpotConstant) constantReflection.forString(value));
+ arrayContent[i] = reg.asValue(target.getLIRKind(JavaKind.Object));
+ } else {
+ Assert.fail("unexpected value");
+ }
+ }
+ array.setValues(arrayContent, arrayKind);
+
+ // build return object
+ ResolvedJavaField[] fields = retType.getInstanceFields(true);
+ JavaValue[] retContent = new JavaValue[fields.length];
+ JavaKind[] retKind = new JavaKind[fields.length];
+ for (int i = 0; i < fields.length; i++) {
+ retKind[i] = fields[i].getJavaKind();
+ switch (retKind[i]) {
+ case Long: // template.longField
+ retContent[i] = JavaConstant.forLong(template.longField);
+ break;
+ case Int: // template.intField
+ Register intReg = asm.emitLoadInt(template.intField);
+ retContent[i] = asm.emitIntToStack(intReg);
+ break;
+ case Float: // template.floatField
+ Register fReg = asm.emitLoadFloat(template.floatField);
+ retContent[i] = fReg.asValue(target.getLIRKind(JavaKind.Float));
+ break;
+ case Object: // template.arrayField
+ retContent[i] = array;
+ break;
+ default:
+ Assert.fail("unexpected field");
+ }
+ }
+ ret.setValues(retContent, retKind);
+
+ return vobjs.toArray(new VirtualObject[0]);
+ }
+
+ @Test
+ public void testBuildObject() {
+ test(this::compileBuildObject, getMethod("buildObject"), 7, JavaKind.Object);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/code/amd64/AMD64TestAssembler.java Tue Dec 15 16:55:24 2015 +0100
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 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 compiler.jvmci.code.amd64;
+
+import jdk.vm.ci.amd64.AMD64;
+import jdk.vm.ci.amd64.AMD64Kind;
+import jdk.vm.ci.code.CodeCacheProvider;
+import jdk.vm.ci.code.CompilationResult;
+import jdk.vm.ci.code.CompilationResult.ConstantReference;
+import jdk.vm.ci.code.CompilationResult.DataSectionReference;
+import jdk.vm.ci.code.DataSection.Data;
+import jdk.vm.ci.code.DebugInfo;
+import jdk.vm.ci.code.InfopointReason;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.StackSlot;
+import jdk.vm.ci.hotspot.HotSpotConstant;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.LIRKind;
+import jdk.vm.ci.meta.VMConstant;
+
+import compiler.jvmci.code.TestAssembler;
+
+public class AMD64TestAssembler extends TestAssembler {
+
+ public AMD64TestAssembler(CompilationResult result, CodeCacheProvider codeCache) {
+ super(result, codeCache, 16, 16, AMD64Kind.DWORD, AMD64.rax, AMD64.rcx, AMD64.rdi, AMD64.r8, AMD64.r9, AMD64.r10);
+ }
+
+ public void emitPrologue() {
+ emitByte(0x50 | AMD64.rbp.encoding); // PUSH rbp
+ emitMove(true, AMD64.rbp, AMD64.rsp); // MOV rbp, rsp
+ }
+
+ public void emitGrowStack(int size) {
+ // SUB rsp, size
+ emitByte(0x48);
+ emitByte(0x81);
+ emitByte(0xEC);
+ emitInt(size);
+ }
+
+ public Register emitIntArg0() {
+ return AMD64.rsi;
+ }
+
+ public Register emitIntArg1() {
+ return AMD64.rdx;
+ }
+
+ private void emitREX(boolean w, int r, int x, int b) {
+ int wrxb = (w ? 0x08 : 0) | ((r >> 3) << 2) | ((x >> 3) << 1) | (b >> 3);
+ if (wrxb != 0) {
+ emitByte(0x40 | wrxb);
+ }
+ }
+
+ private void emitModRMReg(boolean w, int opcode, int r, int m) {
+ emitREX(w, r, 0, m);
+ emitByte((byte) opcode);
+ emitByte((byte) 0xC0 | ((r & 0x7) << 3) | (m & 0x7));
+ }
+
+ private void emitModRMMemory(boolean w, int opcode, int r, int b, int offset) {
+ emitREX(w, r, 0, b);
+ emitByte((byte) opcode);
+ emitByte((byte) 0x80 | ((r & 0x7) << 3) | (b & 0x7));
+ emitInt(offset);
+ }
+
+ public Register emitLoadInt(int c) {
+ Register ret = newRegister();
+ emitREX(false, 0, 0, ret.encoding);
+ emitByte(0xB8 | (ret.encoding & 0x7)); // MOV r32, imm32
+ emitInt(c);
+ return ret;
+ }
+
+ public Register emitLoadLong(long c) {
+ Register ret = newRegister();
+ emitREX(true, 0, 0, ret.encoding);
+ emitByte(0xB8 | (ret.encoding & 0x7)); // MOV r64, imm64
+ emitLong(c);
+ return ret;
+ }
+
+ public Register emitLoadFloat(float c) {
+ Data data = codeCache.createDataItem(JavaConstant.forFloat(c));
+ DataSectionReference ref = result.getDataSection().insertData(data);
+ result.recordDataPatch(position(), ref);
+ Register ret = AMD64.xmm0;
+ emitREX(false, ret.encoding, 0, 0);
+ emitByte(0xF3);
+ emitByte(0x0F);
+ emitByte(0x10); // MOVSS xmm1, xmm2/m32
+ emitByte(0x05 | ((ret.encoding & 0x7) << 3)); // xmm, [rip+offset]
+ emitInt(0xDEADDEAD);
+ return ret;
+ }
+
+ public Register emitLoadPointer(HotSpotConstant c) {
+ result.recordDataPatch(position(), new ConstantReference((VMConstant) c));
+ if (c.isCompressed()) {
+ Register ret = newRegister();
+ emitREX(false, 0, 0, ret.encoding);
+ emitByte(0xB8 | (ret.encoding & 0x7)); // MOV r32, imm32
+ emitInt(0xDEADDEAD);
+ return ret;
+ } else {
+ return emitLoadLong(0xDEADDEADDEADDEADl);
+ }
+ }
+
+ private Register emitLoadPointer(DataSectionReference ref, boolean narrow) {
+ result.recordDataPatch(position(), ref);
+ Register ret = newRegister();
+ emitREX(!narrow, ret.encoding, 0, 0);
+ emitByte(0x8B); // MOV r64,r/m64
+ emitByte(0x05 | ((ret.encoding & 0x7) << 3)); // r64, [rip+offset]
+ emitInt(0xDEADDEAD);
+ return ret;
+ }
+
+ public Register emitLoadPointer(DataSectionReference ref) {
+ return emitLoadPointer(ref, false);
+ }
+
+ public Register emitLoadNarrowPointer(DataSectionReference ref) {
+ return emitLoadPointer(ref, true);
+ }
+
+ public Register emitLoadPointer(Register b, int offset) {
+ Register ret = newRegister();
+ emitModRMMemory(true, 0x8B, ret.encoding, b.encoding, offset); // MOV r64,r/m64
+ return ret;
+ }
+
+ public StackSlot emitIntToStack(Register a) {
+ StackSlot ret = newStackSlot(LIRKind.value(AMD64Kind.DWORD));
+ emitModRMMemory(false, 0x89, a.encoding, AMD64.rbp.encoding, ret.getRawOffset() + 16); // MOV r/m32,r32
+ return ret;
+ }
+
+ public StackSlot emitLongToStack(Register a) {
+ StackSlot ret = newStackSlot(LIRKind.value(AMD64Kind.QWORD));
+ emitModRMMemory(true, 0x89, a.encoding, AMD64.rbp.encoding, ret.getRawOffset() + 16); // MOV r/m64,r64
+ return ret;
+ }
+
+ public StackSlot emitFloatToStack(Register a) {
+ StackSlot ret = newStackSlot(LIRKind.value(AMD64Kind.SINGLE));
+ emitREX(false, a.encoding, 0, 0);
+ emitByte(0xF3);
+ emitByte(0x0F);
+ emitByte(0x11); // MOVSS xmm2/m32, xmm1
+ emitByte(0x85 | ((a.encoding & 0x7) << 3)); // [rbp+offset]
+ emitInt(ret.getRawOffset() + 16);
+ return ret;
+ }
+
+ public StackSlot emitPointerToStack(Register a) {
+ StackSlot ret = newStackSlot(LIRKind.reference(AMD64Kind.QWORD));
+ emitModRMMemory(true, 0x89, a.encoding, AMD64.rbp.encoding, ret.getRawOffset() + 16); // MOV r/m64,r64
+ return ret;
+ }
+
+ public StackSlot emitNarrowPointerToStack(Register a) {
+ StackSlot ret = newStackSlot(LIRKind.reference(AMD64Kind.DWORD));
+ emitModRMMemory(false, 0x89, a.encoding, AMD64.rbp.encoding, ret.getRawOffset() + 16); // MOV r/m32,r32
+ return ret;
+ }
+
+ public Register emitUncompressPointer(Register compressed, long base, int shift) {
+ if (shift > 0) {
+ emitModRMReg(true, 0xC1, 4, compressed.encoding);
+ emitByte(shift);
+ }
+ if (base == 0) {
+ return compressed;
+ } else {
+ Register tmp = emitLoadLong(base);
+ emitModRMReg(true, 0x03, tmp.encoding, compressed.encoding);
+ return tmp;
+ }
+ }
+
+ public Register emitIntAdd(Register a, Register b) {
+ emitModRMReg(false, 0x03, a.encoding, b.encoding);
+ return a;
+ }
+
+ private void emitMove(boolean w, Register to, Register from) {
+ if (to != from) {
+ emitModRMReg(w, 0x8B, to.encoding, from.encoding);
+ }
+ }
+
+ public void emitIntRet(Register a) {
+ emitMove(false, AMD64.rax, a); // MOV eax, ...
+ emitMove(true, AMD64.rsp, AMD64.rbp); // MOV rsp, rbp
+ emitByte(0x58 | AMD64.rbp.encoding); // POP rbp
+ emitByte(0xC3); // RET
+ }
+
+ public void emitPointerRet(Register a) {
+ emitMove(true, AMD64.rax, a); // MOV rax, ...
+ emitMove(true, AMD64.rsp, AMD64.rbp); // MOV rsp, rbp
+ emitByte(0x58 | AMD64.rbp.encoding); // POP rbp
+ emitByte(0xC3); // RET
+ }
+
+ public void emitTrap(DebugInfo info) {
+ result.recordInfopoint(position(), info, InfopointReason.IMPLICIT_EXCEPTION);
+ // MOV rax, [0]
+ emitByte(0x8B);
+ emitByte(0x04);
+ emitByte(0x25);
+ emitInt(0);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/code/sparc/SPARCTestAssembler.java Tue Dec 15 16:55:24 2015 +0100
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 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 compiler.jvmci.code.sparc;
+
+import jdk.vm.ci.code.CodeCacheProvider;
+import jdk.vm.ci.code.CompilationResult;
+import jdk.vm.ci.code.CompilationResult.ConstantReference;
+import jdk.vm.ci.code.CompilationResult.DataSectionReference;
+import jdk.vm.ci.code.DataSection.Data;
+import jdk.vm.ci.code.DebugInfo;
+import jdk.vm.ci.code.InfopointReason;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.StackSlot;
+import jdk.vm.ci.hotspot.HotSpotConstant;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.LIRKind;
+import jdk.vm.ci.meta.VMConstant;
+import jdk.vm.ci.sparc.SPARC;
+import jdk.vm.ci.sparc.SPARCKind;
+
+import compiler.jvmci.code.TestAssembler;
+
+public class SPARCTestAssembler extends TestAssembler {
+
+ private static final int MASK13 = (1 << 13) - 1;
+
+ public SPARCTestAssembler(CompilationResult result, CodeCacheProvider codeCache) {
+ super(result, codeCache, 0, 16, SPARCKind.WORD, SPARC.l0, SPARC.l1, SPARC.l2, SPARC.l3, SPARC.l4, SPARC.l5, SPARC.l6, SPARC.l7);
+ }
+
+ private void emitOp2(Register rd, int op2, int imm22) {
+ emitInt((0b00 << 30) | (rd.encoding << 25) | (op2 << 22) | imm22);
+ }
+
+ private void emitOp3(int op, Register rd, int op3, Register rs1, Register rs2) {
+ emitInt((op << 30) | (rd.encoding << 25) | (op3 << 19) | (rs1.encoding << 14) | rs2.encoding);
+ }
+
+ private void emitOp3(int op, Register rd, int op3, Register rs1, int simm13) {
+ emitInt((op << 30) | (rd.encoding << 25) | (op3 << 19) | (rs1.encoding << 14) | (1 << 13) | (simm13 & MASK13));
+ }
+
+ private void emitNop() {
+ emitInt(1 << 24);
+ }
+
+ public void emitPrologue() {
+ emitOp3(0b10, SPARC.sp, 0b111100, SPARC.sp, -SPARC.REGISTER_SAFE_AREA_SIZE); // SAVE sp, -128, sp
+ }
+
+ @Override
+ public void finish() {
+ frameSize += SPARC.REGISTER_SAFE_AREA_SIZE;
+ super.finish();
+ }
+
+ public void emitGrowStack(int size) {
+ emitOp3(0b10, SPARC.sp, 0b000100, SPARC.sp, size); // SUB sp, size, sp
+ }
+
+ public Register emitIntArg0() {
+ return SPARC.i0;
+ }
+
+ public Register emitIntArg1() {
+ return SPARC.i1;
+ }
+
+ public Register emitLoadInt(int c) {
+ Register ret = newRegister();
+ int hi = c >>> 10;
+ int lo = c & ((1 << 10) - 1);
+ if (hi == 0) {
+ emitOp3(0b10, ret, 0b000010, SPARC.g0, lo); // OR g0, lo, ret
+ } else {
+ emitOp2(ret, 0b100, hi); // SETHI hi, ret
+ if (lo != 0) {
+ emitOp3(0b10, ret, 0b000010, ret, lo); // OR ret, lo, ret
+ }
+ }
+ return ret;
+ }
+
+ public Register emitLoadLong(long c) {
+ if ((c & 0xFFFFFFFF) == c) {
+ return emitLoadInt((int) c);
+ } else {
+ Data data = codeCache.createDataItem(JavaConstant.forLong(c));
+ DataSectionReference ref = result.getDataSection().insertData(data);
+ return emitLoadPointer(ref);
+ }
+ }
+
+ private void emitPatchableSethi(Register ret, boolean wide) {
+ int startPos = position();
+ emitOp2(ret, 0b100, 0); // SETHI 0, ret
+ if (wide) {
+ // pad for later patching
+ while (position() < (startPos + 28)) {
+ emitNop();
+ }
+ }
+ }
+
+ public Register emitLoadFloat(float c) {
+ Data data = codeCache.createDataItem(JavaConstant.forFloat(c));
+ DataSectionReference ref = result.getDataSection().insertData(data);
+
+ Register ptr = newRegister();
+ result.recordDataPatch(position(), ref);
+ emitPatchableSethi(ptr, true);
+ emitOp3(0b11, SPARC.f0, 0b100000, ptr, 0); // LDF [ptr+0], f0
+ return SPARC.f0;
+ }
+
+ public Register emitLoadPointer(HotSpotConstant c) {
+ Register ret = newRegister();
+ result.recordDataPatch(position(), new ConstantReference((VMConstant) c));
+
+ emitPatchableSethi(ret, !c.isCompressed());
+ emitOp3(0b10, ret, 0b000010, ret, 0); // OR ret, 0, ret
+
+ return ret;
+ }
+
+ public Register emitLoadPointer(DataSectionReference ref) {
+ Register ret = newRegister();
+ result.recordDataPatch(position(), ref);
+ emitPatchableSethi(ret, true);
+ emitOp3(0b11, ret, 0b001011, ret, 0); // LDX [ret+0], ret
+ return ret;
+ }
+
+ public Register emitLoadNarrowPointer(DataSectionReference ref) {
+ Register ret = newRegister();
+ result.recordDataPatch(position(), ref);
+ emitPatchableSethi(ret, true);
+ emitOp3(0b11, ret, 0b000000, ret, 0); // LDUW [ret+0], ret
+ return ret;
+ }
+
+ public Register emitLoadPointer(Register b, int offset) {
+ Register ret = newRegister();
+ emitOp3(0b11, ret, 0b001011, b, offset); // LDX [b+offset], ret
+ return ret;
+ }
+
+ public StackSlot emitIntToStack(Register a) {
+ StackSlot ret = newStackSlot(LIRKind.value(SPARCKind.WORD));
+ emitOp3(0b11, a, 0b000100, SPARC.fp, ret.getRawOffset() + SPARC.STACK_BIAS); // STW a, [fp+offset]
+ return ret;
+ }
+
+ public StackSlot emitLongToStack(Register a) {
+ StackSlot ret = newStackSlot(LIRKind.value(SPARCKind.XWORD));
+ emitOp3(0b11, a, 0b001110, SPARC.fp, ret.getRawOffset() + SPARC.STACK_BIAS); // STX a, [fp+offset]
+ return ret;
+ }
+
+ public StackSlot emitFloatToStack(Register a) {
+ StackSlot ret = newStackSlot(LIRKind.value(SPARCKind.SINGLE));
+ emitOp3(0b11, a, 0b100100, SPARC.fp, ret.getRawOffset() + SPARC.STACK_BIAS); // STF a, [fp+offset]
+ return ret;
+ }
+
+ public StackSlot emitPointerToStack(Register a) {
+ StackSlot ret = newStackSlot(LIRKind.reference(SPARCKind.XWORD));
+ emitOp3(0b11, a, 0b001110, SPARC.fp, ret.getRawOffset() + SPARC.STACK_BIAS); // STX a, [fp+offset]
+ return ret;
+ }
+
+ public StackSlot emitNarrowPointerToStack(Register a) {
+ StackSlot ret = newStackSlot(LIRKind.reference(SPARCKind.WORD));
+ emitOp3(0b11, a, 0b000100, SPARC.fp, ret.getRawOffset() + SPARC.STACK_BIAS); // STW a, [fp+offset]
+ return ret;
+ }
+
+ public Register emitUncompressPointer(Register compressed, long base, int shift) {
+ Register ret;
+ if (shift > 0) {
+ ret = newRegister();
+ emitOp3(0b10, ret, 0b100101, compressed, shift); // SLL compressed, shift, ret
+ } else {
+ ret = compressed;
+ }
+ if (base == 0) {
+ return ret;
+ } else {
+ Register b = emitLoadLong(base);
+ emitOp3(0b10, b, 0b00000, ret, b); // ADD b, ret, b
+ return b;
+ }
+ }
+
+ public Register emitIntAdd(Register a, Register b) {
+ Register ret = newRegister();
+ emitOp3(0b10, ret, 0b00000, a, b); // ADD a, b, ret
+ return ret;
+ }
+
+ private void emitMove(Register to, Register from) {
+ if (to != from) {
+ emitOp3(0b10, to, 0b000010, from, SPARC.g0); // OR from, g0, to
+ }
+ }
+
+ public void emitIntRet(Register a) {
+ emitPointerRet(a);
+ }
+
+ public void emitPointerRet(Register a) {
+ emitMove(SPARC.i0, a);
+ emitOp3(0b10, SPARC.g0, 0b111000, SPARC.i7, 8); // JMPL [i7+8], g0
+ emitOp3(0b10, SPARC.g0, 0b111101, SPARC.g0, SPARC.g0); // RESTORE g0, g0, g0
+ }
+
+ public void emitTrap(DebugInfo info) {
+ result.recordInfopoint(position(), info, InfopointReason.IMPLICIT_EXCEPTION);
+ emitOp3(0b11, SPARC.g0, 0b001011, SPARC.g0, 0); // LDX [g0+0], g0
+ }
+}