summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Orion Hodson <oth@google.com> 2018-02-26 10:25:41 +0000
committer Orion Hodson <oth@google.com> 2018-02-27 10:05:34 +0000
commit4c213cbf29048bb3df0065c17e82084a4afafc85 (patch)
treee9dcb78de802e2e54a431b2d1945ded6b96fd389
parentc57b3ae06f78b7386b6866a1ea265b3c790026dc (diff)
ART: More refactoring of invoke-custom tests
Moves 952-invoke-custom-kinds into 952-invoke-custom using ASM annotations to generate the necessary bootstrap metadata. Simplify the annotations used by the transformer by replacing MethodHandleKind, LinkerFieldHandle, and LinkerMethodHandle annotations with BootstrapMethod annotation. Bug: 73807070 Test: art/test/run-test --host 952 Change-Id: Ia85e79dea105d84ceaac7c6634b74a7eb232d0ee
-rw-r--r--test/952-invoke-custom-kinds/build22
-rw-r--r--test/952-invoke-custom-kinds/classes/Main.classbin302 -> 0 bytes
-rw-r--r--test/952-invoke-custom-kinds/classes/invokecustom/Interface.classbin152 -> 0 bytes
-rw-r--r--test/952-invoke-custom-kinds/classes/invokecustom/InterfaceImplementor.classbin503 -> 0 bytes
-rw-r--r--test/952-invoke-custom-kinds/classes/invokecustom/InvokeCustom$Interface.classbin239 -> 0 bytes
-rw-r--r--test/952-invoke-custom-kinds/classes/invokecustom/InvokeCustom$InterfaceImplementor.classbin634 -> 0 bytes
-rw-r--r--test/952-invoke-custom-kinds/classes/invokecustom/InvokeCustom.classbin8831 -> 0 bytes
-rw-r--r--test/952-invoke-custom-kinds/classes/invokecustom/Super.classbin468 -> 0 bytes
-rw-r--r--test/952-invoke-custom-kinds/classes/invokecustom/TestGenerator$1.classbin1124 -> 0 bytes
-rw-r--r--test/952-invoke-custom-kinds/classes/invokecustom/TestGenerator.classbin8736 -> 0 bytes
-rw-r--r--test/952-invoke-custom-kinds/expected.txt40
-rw-r--r--test/952-invoke-custom-kinds/info.txt4
-rw-r--r--test/952-invoke-custom/expected.txt5
-rw-r--r--test/952-invoke-custom/src/Main.java1
-rw-r--r--test/952-invoke-custom/src/TestInvocationKinds.java217
-rw-r--r--test/952-invoke-custom/src/TestInvokeCustomWithConcurrentThreads.java14
-rw-r--r--test/952-invoke-custom/src/TestLinkerMethodMinimalArguments.java14
-rw-r--r--test/952-invoke-custom/src/TestLinkerMethodMultipleArgumentTypes.java20
-rw-r--r--test/952-invoke-custom/src/TestLinkerUnrelatedBSM.java29
-rw-r--r--test/952-invoke-custom/src/annotations/BootstrapMethod.java (renamed from test/952-invoke-custom/src/annotations/LinkerMethodHandle.java)17
-rw-r--r--test/952-invoke-custom/src/annotations/CalledByIndy.java14
-rw-r--r--test/952-invoke-custom/src/annotations/LinkerFieldHandle.java36
-rw-r--r--test/952-invoke-custom/src/annotations/MethodHandleKind.java30
-rw-r--r--test/952-invoke-custom/src/transformer/IndyTransformer.java128
24 files changed, 311 insertions, 280 deletions
diff --git a/test/952-invoke-custom-kinds/build b/test/952-invoke-custom-kinds/build
deleted file mode 100644
index a02cdc3769..0000000000
--- a/test/952-invoke-custom-kinds/build
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Stop if something fails.
-set -e
-
-${DX} --dex --min-sdk-version=26 --output=classes.dex classes
-
-zip $TEST_NAME.jar classes.dex
diff --git a/test/952-invoke-custom-kinds/classes/Main.class b/test/952-invoke-custom-kinds/classes/Main.class
deleted file mode 100644
index 6bc04e326a..0000000000
--- a/test/952-invoke-custom-kinds/classes/Main.class
+++ /dev/null
Binary files differ
diff --git a/test/952-invoke-custom-kinds/classes/invokecustom/Interface.class b/test/952-invoke-custom-kinds/classes/invokecustom/Interface.class
deleted file mode 100644
index 5dfe958795..0000000000
--- a/test/952-invoke-custom-kinds/classes/invokecustom/Interface.class
+++ /dev/null
Binary files differ
diff --git a/test/952-invoke-custom-kinds/classes/invokecustom/InterfaceImplementor.class b/test/952-invoke-custom-kinds/classes/invokecustom/InterfaceImplementor.class
deleted file mode 100644
index a11ee696bf..0000000000
--- a/test/952-invoke-custom-kinds/classes/invokecustom/InterfaceImplementor.class
+++ /dev/null
Binary files differ
diff --git a/test/952-invoke-custom-kinds/classes/invokecustom/InvokeCustom$Interface.class b/test/952-invoke-custom-kinds/classes/invokecustom/InvokeCustom$Interface.class
deleted file mode 100644
index e233febbf4..0000000000
--- a/test/952-invoke-custom-kinds/classes/invokecustom/InvokeCustom$Interface.class
+++ /dev/null
Binary files differ
diff --git a/test/952-invoke-custom-kinds/classes/invokecustom/InvokeCustom$InterfaceImplementor.class b/test/952-invoke-custom-kinds/classes/invokecustom/InvokeCustom$InterfaceImplementor.class
deleted file mode 100644
index 41e1d431f2..0000000000
--- a/test/952-invoke-custom-kinds/classes/invokecustom/InvokeCustom$InterfaceImplementor.class
+++ /dev/null
Binary files differ
diff --git a/test/952-invoke-custom-kinds/classes/invokecustom/InvokeCustom.class b/test/952-invoke-custom-kinds/classes/invokecustom/InvokeCustom.class
deleted file mode 100644
index b8dcd5559a..0000000000
--- a/test/952-invoke-custom-kinds/classes/invokecustom/InvokeCustom.class
+++ /dev/null
Binary files differ
diff --git a/test/952-invoke-custom-kinds/classes/invokecustom/Super.class b/test/952-invoke-custom-kinds/classes/invokecustom/Super.class
deleted file mode 100644
index 7906f99d2d..0000000000
--- a/test/952-invoke-custom-kinds/classes/invokecustom/Super.class
+++ /dev/null
Binary files differ
diff --git a/test/952-invoke-custom-kinds/classes/invokecustom/TestGenerator$1.class b/test/952-invoke-custom-kinds/classes/invokecustom/TestGenerator$1.class
deleted file mode 100644
index c3266e49f7..0000000000
--- a/test/952-invoke-custom-kinds/classes/invokecustom/TestGenerator$1.class
+++ /dev/null
Binary files differ
diff --git a/test/952-invoke-custom-kinds/classes/invokecustom/TestGenerator.class b/test/952-invoke-custom-kinds/classes/invokecustom/TestGenerator.class
deleted file mode 100644
index 03dc23396c..0000000000
--- a/test/952-invoke-custom-kinds/classes/invokecustom/TestGenerator.class
+++ /dev/null
Binary files differ
diff --git a/test/952-invoke-custom-kinds/expected.txt b/test/952-invoke-custom-kinds/expected.txt
deleted file mode 100644
index c41b5c6d88..0000000000
--- a/test/952-invoke-custom-kinds/expected.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-bsmLookupStatic []
-Hello World!
-bsmLookupStatic []
-true
-127
-c
-1024
-123456
-1.2
-123456789
-3.5123456789
-String
-bsmLookupStaticWithExtraArgs [1, 123456789, 123.456, 123456.789123]
-targetMethodTest3 from InvokeCustom
-bsmCreateCallSite [MethodHandle(InvokeCustom)void]
-targetMethodTest4 from Super
-bsmLookupStatic []
-targetMethodTest5 1000 + -923 = 77
-targetMethodTest5 returned: 77
-bsmLookupStatic []
-targetMethodTest6 8209686820727 + -1172812402961 = 7036874417766
-targetMethodTest6 returned: 7036874417766
-bsmLookupStatic []
-targetMethodTest7 0.50097656 * -0.50097656 = -0.2509775161743164
-targetMethodTest6 returned: -0.2509775161743164
-bsmLookupStatic []
-targetMethodTest8 First invokedynamic invocation
-bsmLookupStatic []
-targetMethodTest8 Second invokedynamic invocation
-bsmLookupStatic []
-targetMethodTest8 Dupe first invokedynamic invocation
-bsmLookupTest9 [MethodHandle()int, MethodHandle(int)void, MethodHandle(InvokeCustom)float, MethodHandle(InvokeCustom,float)void]
-targetMethodTest9 ()void
-checkStaticFieldTest9: old 0 new 1985229328 expected 1985229328 OK
-checkFieldTest9: old 0.0 new 1.99E-19 expected 1.99E-19 OK
-helperMethodTest9 in class invokecustom.InvokeCustom
-InvokeCustom.<init>(3)
-run() for Test9
-InvokeCustom.privateMethodTest9()
-targetMethodTest9()
diff --git a/test/952-invoke-custom-kinds/info.txt b/test/952-invoke-custom-kinds/info.txt
deleted file mode 100644
index 33b4cffc1d..0000000000
--- a/test/952-invoke-custom-kinds/info.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This test checks call sites and constant method handles in DEX files used
-by invoke-custom.
-
-The class files come from dalvik/dx/tests/135-invoke-custom.
diff --git a/test/952-invoke-custom/expected.txt b/test/952-invoke-custom/expected.txt
index be01c453fb..767cc7e734 100644
--- a/test/952-invoke-custom/expected.txt
+++ b/test/952-invoke-custom/expected.txt
@@ -13,3 +13,8 @@ Linking _add (int,int)int
9000
TestLinkerUnrelatedBSM
Winners 1 Votes 16
+TestInvocationKinds
+testStaticFieldAccessors
+testInstanceFieldAccessors
+testInvokeVirtual => max(77, -3) = 77
+testConstructor => class TestInvocationKinds$Widget
diff --git a/test/952-invoke-custom/src/Main.java b/test/952-invoke-custom/src/Main.java
index 2e1db8200f..0b1c1fffe5 100644
--- a/test/952-invoke-custom/src/Main.java
+++ b/test/952-invoke-custom/src/Main.java
@@ -86,5 +86,6 @@ public class Main extends TestBase {
TestLinkerMethodMultipleArgumentTypes();
TestLinkerUnrelatedBSM.test();
TestInvokeCustomWithConcurrentThreads();
+ TestInvocationKinds.test();
}
}
diff --git a/test/952-invoke-custom/src/TestInvocationKinds.java b/test/952-invoke-custom/src/TestInvocationKinds.java
new file mode 100644
index 0000000000..7b88c18c66
--- /dev/null
+++ b/test/952-invoke-custom/src/TestInvocationKinds.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import annotations.BootstrapMethod;
+import annotations.CalledByIndy;
+import java.lang.invoke.CallSite;
+import java.lang.invoke.ConstantCallSite;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+class TestInvocationKinds extends TestBase {
+ private static int static_field;
+ private double instance_field;
+
+ static CallSite lookupStaticFieldGetter(
+ MethodHandles.Lookup lookup, String name, MethodType methodType) throws Throwable {
+ // methodType = "()LfieldType;"
+ MethodHandle mh =
+ lookup.findStaticGetter(TestInvocationKinds.class, name, methodType.returnType());
+ return new ConstantCallSite(mh);
+ }
+
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(
+ enclosingType = TestInvocationKinds.class,
+ name = "lookupStaticFieldSetter"
+ ),
+ fieldOrMethodName = "static_field",
+ returnType = void.class,
+ parameterTypes = {int.class}
+ )
+ private static void setStaticField(int value) {
+ assertNotReached();
+ }
+
+ static CallSite lookupStaticFieldSetter(
+ MethodHandles.Lookup lookup, String name, MethodType methodType) throws Throwable {
+ // methodType = "(LfieldType;)V"
+ MethodHandle mh =
+ lookup.findStaticSetter(
+ TestInvocationKinds.class, name, methodType.parameterType(0));
+ return new ConstantCallSite(mh);
+ }
+
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(
+ enclosingType = TestInvocationKinds.class,
+ name = "lookupStaticFieldGetter"
+ ),
+ fieldOrMethodName = "static_field",
+ returnType = int.class,
+ parameterTypes = {}
+ )
+ private static int getStaticField() {
+ assertNotReached();
+ return 0;
+ }
+
+ static CallSite lookupInstanceFieldSetter(
+ MethodHandles.Lookup lookup, String name, MethodType methodType) throws Throwable {
+ // methodType = "(Lreceiver;LfieldType;)V"
+ MethodHandle mh =
+ lookup.findSetter(methodType.parameterType(0), name, methodType.parameterType(1));
+ return new ConstantCallSite(mh);
+ }
+
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(
+ enclosingType = TestInvocationKinds.class,
+ name = "lookupInstanceFieldSetter"
+ ),
+ fieldOrMethodName = "instance_field",
+ returnType = void.class,
+ parameterTypes = {TestInvocationKinds.class, double.class}
+ )
+ private static void setInstanceField(TestInvocationKinds instance, double value) {
+ assertNotReached();
+ instance.instance_field = Double.NaN;
+ }
+
+ static CallSite lookupInstanceFieldGetter(
+ MethodHandles.Lookup lookup, String name, MethodType methodType) throws Throwable {
+ // methodType = "(Lreceiver;)LfieldType;"
+ MethodHandle mh =
+ lookup.findGetter(methodType.parameterType(0), name, methodType.returnType());
+ return new ConstantCallSite(mh);
+ }
+
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(
+ enclosingType = TestInvocationKinds.class,
+ name = "lookupInstanceFieldGetter"
+ ),
+ fieldOrMethodName = "instance_field",
+ returnType = double.class,
+ parameterTypes = {TestInvocationKinds.class}
+ )
+ private static double getInstanceField(TestInvocationKinds instance) {
+ assertNotReached();
+ return Double.NaN;
+ }
+
+ private static void testStaticFieldAccessors() {
+ System.out.println("testStaticFieldAccessors");
+ setStaticField(3);
+ assertEquals(static_field, 3);
+ setStaticField(4);
+ assertEquals(static_field, 4);
+ assertEquals(static_field, getStaticField());
+ static_field = Integer.MAX_VALUE;
+ assertEquals(Integer.MAX_VALUE, getStaticField());
+ }
+
+ private static void testInstanceFieldAccessors() {
+ System.out.println("testInstanceFieldAccessors");
+ TestInvocationKinds instance = new TestInvocationKinds();
+ instance.instance_field = Double.MIN_VALUE;
+ setInstanceField(instance, Math.PI);
+ assertEquals(Math.PI, instance.instance_field);
+ instance.instance_field = Math.E;
+ assertEquals(Math.E, getInstanceField(instance));
+ }
+
+ private static CallSite lookupVirtual(
+ MethodHandles.Lookup lookup, String name, MethodType methodType) throws Throwable {
+ // To get the point-of-use and invokedynamic to work the methodType here has the
+ // receiver type as the leading paramter which needs to be dropped for findVirtual().
+ MethodType mt = methodType.dropParameterTypes(0, 1);
+ MethodHandle mh = lookup.findVirtual(TestInvocationKinds.class, name, mt);
+ return new ConstantCallSite(mh);
+ }
+
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(enclosingType = TestInvocationKinds.class, name = "lookupVirtual"),
+ fieldOrMethodName = "getMaxIntegerValue",
+ returnType = int.class,
+ parameterTypes = {TestInvocationKinds.class, int.class, int.class}
+ )
+ private static int maxIntegerValue(TestInvocationKinds receiver, int x, int y) {
+ assertNotReached();
+ return 0;
+ }
+
+ public int getMaxIntegerValue(int x, int y) {
+ return x > y ? x : y;
+ }
+
+ static void testInvokeVirtual() {
+ System.out.print("testInvokeVirtual => max(77, -3) = ");
+ TestInvocationKinds receiver = new TestInvocationKinds();
+ int result = maxIntegerValue(receiver, 77, -3);
+ System.out.println(result);
+ }
+
+ static class Widget {
+ int value;
+ public Widget(int value) {}
+ }
+
+ private static CallSite lookupConstructor(
+ MethodHandles.Lookup lookup, String name, MethodType methodType) throws Throwable {
+ // methodType = (constructorParams);classToBeConstructed
+ Class<?> cls = methodType.returnType();
+ MethodType constructorMethodType = methodType.changeReturnType(void.class);
+ MethodHandle mh = lookup.findConstructor(cls, constructorMethodType);
+ return new ConstantCallSite(mh);
+ }
+
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(
+ enclosingType = TestInvocationKinds.class,
+ name = "lookupConstructor"
+ ),
+ fieldOrMethodName = "unused",
+ returnType = Widget.class,
+ parameterTypes = {int.class}
+ )
+ private static Widget makeWidget(int v) {
+ assertNotReached();
+ return null;
+ }
+
+ static void testConstructor() {
+ System.out.print("testConstructor => ");
+ Widget receiver = makeWidget(3);
+ assertEquals(Widget.class, receiver.getClass());
+ System.out.println(receiver.getClass());
+ }
+
+ public static void test() {
+ System.out.println(TestInvocationKinds.class.getName());
+ testStaticFieldAccessors();
+ testInstanceFieldAccessors();
+ testInvokeVirtual();
+ testConstructor();
+ }
+}
diff --git a/test/952-invoke-custom/src/TestInvokeCustomWithConcurrentThreads.java b/test/952-invoke-custom/src/TestInvokeCustomWithConcurrentThreads.java
index 761d1820db..2ef7ff7e70 100644
--- a/test/952-invoke-custom/src/TestInvokeCustomWithConcurrentThreads.java
+++ b/test/952-invoke-custom/src/TestInvokeCustomWithConcurrentThreads.java
@@ -14,9 +14,8 @@
* limitations under the License.
*/
+import annotations.BootstrapMethod;
import annotations.CalledByIndy;
-import annotations.LinkerMethodHandle;
-import annotations.MethodHandleKind;
import java.lang.invoke.CallSite;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
@@ -66,16 +65,15 @@ public class TestInvokeCustomWithConcurrentThreads extends TestBase implements R
}
@CalledByIndy(
- invokeMethodHandle =
- @LinkerMethodHandle(
- kind = MethodHandleKind.INVOKE_STATIC,
+ bootstrapMethod =
+ @BootstrapMethod(
enclosingType = TestInvokeCustomWithConcurrentThreads.class,
name = "linkerMethod",
- argumentTypes = {MethodHandles.Lookup.class, String.class, MethodType.class}
+ parameterTypes = {MethodHandles.Lookup.class, String.class, MethodType.class}
),
- name = "setCalled",
+ fieldOrMethodName = "setCalled",
returnType = int.class,
- argumentTypes = {int.class}
+ parameterTypes = {int.class}
)
private static int setCalled(int index) {
called[index].getAndIncrement();
diff --git a/test/952-invoke-custom/src/TestLinkerMethodMinimalArguments.java b/test/952-invoke-custom/src/TestLinkerMethodMinimalArguments.java
index 74ac3cd15e..ff598bb24f 100644
--- a/test/952-invoke-custom/src/TestLinkerMethodMinimalArguments.java
+++ b/test/952-invoke-custom/src/TestLinkerMethodMinimalArguments.java
@@ -14,9 +14,8 @@
* limitations under the License.
*/
+import annotations.BootstrapMethod;
import annotations.CalledByIndy;
-import annotations.LinkerMethodHandle;
-import annotations.MethodHandleKind;
import java.lang.invoke.CallSite;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
@@ -32,16 +31,15 @@ public class TestLinkerMethodMinimalArguments extends TestBase {
static final int FAILURE_TYPE_TARGET_METHOD_THROWS = 3;
@CalledByIndy(
- invokeMethodHandle =
- @LinkerMethodHandle(
- kind = MethodHandleKind.INVOKE_STATIC,
+ bootstrapMethod =
+ @BootstrapMethod(
enclosingType = TestLinkerMethodMinimalArguments.class,
- argumentTypes = {MethodHandles.Lookup.class, String.class, MethodType.class},
+ parameterTypes = {MethodHandles.Lookup.class, String.class, MethodType.class},
name = "linkerMethod"
),
- name = "_add",
+ fieldOrMethodName = "_add",
returnType = int.class,
- argumentTypes = {int.class, int.class}
+ parameterTypes = {int.class, int.class}
)
private static int add(int a, int b) {
assertNotReached();
diff --git a/test/952-invoke-custom/src/TestLinkerMethodMultipleArgumentTypes.java b/test/952-invoke-custom/src/TestLinkerMethodMultipleArgumentTypes.java
index acb698675f..0015c00844 100644
--- a/test/952-invoke-custom/src/TestLinkerMethodMultipleArgumentTypes.java
+++ b/test/952-invoke-custom/src/TestLinkerMethodMultipleArgumentTypes.java
@@ -14,10 +14,9 @@
* limitations under the License.
*/
+import annotations.BootstrapMethod;
import annotations.CalledByIndy;
import annotations.Constant;
-import annotations.LinkerMethodHandle;
-import annotations.MethodHandleKind;
import java.lang.invoke.CallSite;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
@@ -29,12 +28,11 @@ public class TestLinkerMethodMultipleArgumentTypes extends TestBase {
private static int bootstrapRunCount = 0;
@CalledByIndy(
- invokeMethodHandle =
- @LinkerMethodHandle(
- kind = MethodHandleKind.INVOKE_STATIC,
+ bootstrapMethod =
+ @BootstrapMethod(
enclosingType = TestLinkerMethodMultipleArgumentTypes.class,
name = "linkerMethod",
- argumentTypes = {
+ parameterTypes = {
MethodHandles.Lookup.class,
String.class,
MethodType.class,
@@ -50,7 +48,10 @@ public class TestLinkerMethodMultipleArgumentTypes extends TestBase {
long.class
}
),
- methodHandleExtraArgs = {
+ fieldOrMethodName = "_add",
+ returnType = int.class,
+ parameterTypes = {int.class, int.class},
+ constantArgumentsForBootstrapMethod = {
@Constant(intValue = -1),
@Constant(intValue = 1),
@Constant(intValue = (int) 'a'),
@@ -61,10 +62,7 @@ public class TestLinkerMethodMultipleArgumentTypes extends TestBase {
@Constant(stringValue = "Hello"),
@Constant(classValue = TestLinkerMethodMultipleArgumentTypes.class),
@Constant(longValue = 123456789L)
- },
- name = "_add",
- returnType = int.class,
- argumentTypes = {int.class, int.class}
+ }
)
private static int add(int a, int b) {
assertNotReached();
diff --git a/test/952-invoke-custom/src/TestLinkerUnrelatedBSM.java b/test/952-invoke-custom/src/TestLinkerUnrelatedBSM.java
index 3a63b332b6..139a1720f4 100644
--- a/test/952-invoke-custom/src/TestLinkerUnrelatedBSM.java
+++ b/test/952-invoke-custom/src/TestLinkerUnrelatedBSM.java
@@ -14,20 +14,18 @@
* limitations under the License.
*/
+import annotations.BootstrapMethod;
import annotations.CalledByIndy;
import annotations.Constant;
-import annotations.LinkerMethodHandle;
-import annotations.MethodHandleKind;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
class TestLinkerUnrelatedBSM extends TestBase {
@CalledByIndy(
- invokeMethodHandle =
- @LinkerMethodHandle(
- kind = MethodHandleKind.INVOKE_STATIC,
+ bootstrapMethod =
+ @BootstrapMethod(
enclosingType = UnrelatedBSM.class,
- argumentTypes = {
+ parameterTypes = {
MethodHandles.Lookup.class,
String.class,
MethodType.class,
@@ -35,10 +33,10 @@ class TestLinkerUnrelatedBSM extends TestBase {
},
name = "bsm"
),
- methodHandleExtraArgs = {@Constant(classValue = TestLinkerUnrelatedBSM.class)},
- name = "_addf",
+ fieldOrMethodName = "_addf",
returnType = float.class,
- argumentTypes = {float.class, float.class}
+ parameterTypes = {float.class, float.class},
+ constantArgumentsForBootstrapMethod = {@Constant(classValue = TestLinkerUnrelatedBSM.class)}
)
private static float addf(float a, float b) {
assertNotReached();
@@ -50,11 +48,10 @@ class TestLinkerUnrelatedBSM extends TestBase {
}
@CalledByIndy(
- invokeMethodHandle =
- @LinkerMethodHandle(
- kind = MethodHandleKind.INVOKE_STATIC,
+ bootstrapMethod =
+ @BootstrapMethod(
enclosingType = UnrelatedBSM.class,
- argumentTypes = {
+ parameterTypes = {
MethodHandles.Lookup.class,
String.class,
MethodType.class,
@@ -62,10 +59,10 @@ class TestLinkerUnrelatedBSM extends TestBase {
},
name = "bsm"
),
- methodHandleExtraArgs = {@Constant(classValue = TestLinkerUnrelatedBSM.class)},
- name = "_subf",
+ fieldOrMethodName = "_subf",
returnType = float.class,
- argumentTypes = {float.class, float.class}
+ parameterTypes = {float.class, float.class},
+ constantArgumentsForBootstrapMethod = {@Constant(classValue = TestLinkerUnrelatedBSM.class)}
)
private static float subf(float a, float b) {
assertNotReached();
diff --git a/test/952-invoke-custom/src/annotations/LinkerMethodHandle.java b/test/952-invoke-custom/src/annotations/BootstrapMethod.java
index e0e56c578d..c16783007f 100644
--- a/test/952-invoke-custom/src/annotations/LinkerMethodHandle.java
+++ b/test/952-invoke-custom/src/annotations/BootstrapMethod.java
@@ -21,18 +21,25 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.invoke.CallSite;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
-/** Describe a linker method to a method. */
+/**
+ * Describes a bootstrap method that performs method handle resolution on behalf of an
+ * invoke-dynamic instruction.
+ */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
-public @interface LinkerMethodHandle {
- MethodHandleKind kind();
-
+public @interface BootstrapMethod {
+ /** The class containing the bootstrap method. */
Class<?> enclosingType();
+ /** The bootstrap method name. */
String name();
+ /** The return type of the bootstrap method. */
Class<?> returnType() default CallSite.class;
- Class<?>[] argumentTypes() default {};
+ /** The parameter types of the bootstrap method. */
+ Class<?>[] parameterTypes() default {Lookup.class, String.class, MethodType.class};
}
diff --git a/test/952-invoke-custom/src/annotations/CalledByIndy.java b/test/952-invoke-custom/src/annotations/CalledByIndy.java
index 17b8259af4..c4d13a2af4 100644
--- a/test/952-invoke-custom/src/annotations/CalledByIndy.java
+++ b/test/952-invoke-custom/src/annotations/CalledByIndy.java
@@ -28,15 +28,17 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CalledByIndy {
- LinkerMethodHandle[] invokeMethodHandle() default {};
+ /** Resolver metadata for bootstrapping */
+ BootstrapMethod[] bootstrapMethod() default {};
- LinkerFieldHandle[] fieldMethodHandle() default {};
-
- String name();
+ /** Field or method name. */
+ String fieldOrMethodName();
+ /** Return type of method() or field getter() */
Class<?> returnType() default void.class;
- Class<?>[] argumentTypes() default {};
+ /** Types of parameters for method or field setter() */
+ Class<?>[] parameterTypes() default {};
- Constant[] methodHandleExtraArgs() default {};
+ Constant[] constantArgumentsForBootstrapMethod() default {};
}
diff --git a/test/952-invoke-custom/src/annotations/LinkerFieldHandle.java b/test/952-invoke-custom/src/annotations/LinkerFieldHandle.java
deleted file mode 100644
index a3efe24107..0000000000
--- a/test/952-invoke-custom/src/annotations/LinkerFieldHandle.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package annotations;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.invoke.CallSite;
-
-/** Describe a linker method to a field. */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.ANNOTATION_TYPE)
-public @interface LinkerFieldHandle {
- MethodHandleKind kind();
-
- Class<?> enclosingType();
-
- String name();
-
- Class<?> type() default CallSite.class;
-}
diff --git a/test/952-invoke-custom/src/annotations/MethodHandleKind.java b/test/952-invoke-custom/src/annotations/MethodHandleKind.java
deleted file mode 100644
index 5847e2f39f..0000000000
--- a/test/952-invoke-custom/src/annotations/MethodHandleKind.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package annotations;
-
-/** MethodHandle invocations kinds supported by invokedynamic */
-public enum MethodHandleKind {
- GET_FIELD,
- GET_STATIC,
- PUT_FIELD,
- PUT_STATIC,
- INVOKE_VIRTUAL,
- INVOKE_STATIC,
- INVOKE_SPECIAL,
- INVOKE_CONSTRUCTOR,
- INVOKE_INTERFACE
-}
diff --git a/test/952-invoke-custom/src/transformer/IndyTransformer.java b/test/952-invoke-custom/src/transformer/IndyTransformer.java
index 286c09859d..45cb4760c9 100644
--- a/test/952-invoke-custom/src/transformer/IndyTransformer.java
+++ b/test/952-invoke-custom/src/transformer/IndyTransformer.java
@@ -15,11 +15,9 @@
*/
package transformer;
+import annotations.BootstrapMethod;
import annotations.CalledByIndy;
import annotations.Constant;
-import annotations.LinkerFieldHandle;
-import annotations.LinkerMethodHandle;
-import annotations.MethodHandleKind;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.invoke.MethodType;
@@ -43,18 +41,17 @@ import org.objectweb.asm.Type;
/**
* Class for inserting invoke-dynamic instructions in annotated Java class files.
*
- * This class replaces static method invocations of annotated methods
- * with invoke-dynamic instructions. Suppose a method is annotated as:
+ * <p>This class replaces static method invocations of annotated methods with invoke-dynamic
+ * instructions. Suppose a method is annotated as: <code>
*
* @CalledByIndy(
- * invokeMethodHandle =
- * @LinkerMethodHandle(
- * kind = MethodHandleKind.INVOKE_STATIC,
- * enclosingType = TestLinkerMethodMinimalArguments.class,
- * argumentTypes = {MethodHandles.Lookup.class, String.class, MethodType.class},
- * name = "linkerMethod"
- * ),
- * name = "magicAdd",
+ * bootstrapMethod =
+ * @BootstrapMethod(
+ * enclosingType = TestLinkerMethodMinimalArguments.class,
+ * parameterTypes = {MethodHandles.Lookup.class, String.class, MethodType.class},
+ * name = "linkerMethod"
+ * ),
+ * fieldOdMethodName = "magicAdd",
* returnType = int.class,
* argumentTypes = {int.class, int.class}
* )
@@ -66,13 +63,11 @@ import org.objectweb.asm.Type;
* return x + y;
* }
*
- * Then invokestatic bytecodes targeting the add() method will be
- * replaced invokedynamic instructions targetting the CallSite that is
- * construction by the bootstrap method described by the @CalledByIndy
- * annotation.
+ * </code> Then invokestatic bytecodes targeting the add() method will be replaced invokedynamic
+ * instructions targetting the CallSite that is construction by the bootstrap method described by
+ * the @CalledByIndy annotation.
*
- * In the example above, this results in add() being replaced by
- * invocations of magicAdd().
+ * <p>In the example above, this results in add() being replaced by invocations of magicAdd().
*/
class IndyTransformer {
@@ -101,7 +96,7 @@ class IndyTransformer {
if (opcode == org.objectweb.asm.Opcodes.INVOKESTATIC) {
CalledByIndy callsite = callsiteMap.get(name);
if (callsite != null) {
- insertIndy(callsite.name(), desc, callsite);
+ insertIndy(callsite.fieldOrMethodName(), desc, callsite);
return;
}
}
@@ -109,80 +104,26 @@ class IndyTransformer {
}
private void insertIndy(String name, String desc, CalledByIndy callsite) {
- Handle bsm = buildBootstrapMethodHandle(callsite);
- Object[] bsmArgs = buildBootstrapArguments(callsite);
+ Handle bsm = buildBootstrapMethodHandle(callsite.bootstrapMethod()[0]);
+ Object[] bsmArgs =
+ buildBootstrapArguments(callsite.constantArgumentsForBootstrapMethod());
mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
}
- private Handle buildBootstrapMethodHandle(CalledByIndy callsite) {
- MethodHandleKind kind;
- if (callsite.fieldMethodHandle().length != 0) {
- return buildBootstrapMethodHandleForField(callsite.fieldMethodHandle()[0]);
- } else if (callsite.invokeMethodHandle().length != 0) {
- return buildBootstrapMethodHandleForMethod(
- callsite.invokeMethodHandle()[0]);
- } else {
- throw new Error("Missing linker method handle in CalledByIndy annotation");
- }
- }
-
- private Handle buildBootstrapMethodHandleForField(LinkerFieldHandle fieldHandle) {
- int handleKind;
- switch (fieldHandle.kind()) {
- case GET_FIELD:
- handleKind = Opcodes.H_GETFIELD;
- break;
- case GET_STATIC:
- handleKind = Opcodes.H_GETSTATIC;
- break;
- case PUT_FIELD:
- handleKind = Opcodes.H_PUTFIELD;
- break;
- case PUT_STATIC:
- handleKind = Opcodes.H_PUTSTATIC;
- break;
- default:
- throw new Error("Unknown field invocation kind: " + fieldHandle.kind());
- }
- Class<?> resolverClass = fieldHandle.enclosingType();
- String resolverMethod = fieldHandle.name();
- Class<?> resolverReturnType = fieldHandle.type();
-
- // TODO: arguments types to invoke resolver with (default + extra args).
- throw new Error("WIP");
- }
-
- private Handle buildBootstrapMethodHandleForMethod(
- LinkerMethodHandle methodHandle) {
- int handleKind;
- switch (methodHandle.kind()) {
- case INVOKE_CONSTRUCTOR:
- handleKind = Opcodes.H_NEWINVOKESPECIAL;
- break;
- case INVOKE_INTERFACE:
- handleKind = Opcodes.H_INVOKEINTERFACE;
- break;
- case INVOKE_SPECIAL:
- handleKind = Opcodes.H_INVOKESPECIAL;
- break;
- case INVOKE_STATIC:
- handleKind = Opcodes.H_INVOKESTATIC;
- break;
- case INVOKE_VIRTUAL:
- handleKind = Opcodes.H_INVOKEVIRTUAL;
- break;
- default:
- throw new Error(
- "Unknown method invocation kind: " + methodHandle.kind());
- }
- String className = Type.getInternalName(methodHandle.enclosingType());
- String methodName = methodHandle.name();
+ private Handle buildBootstrapMethodHandle(BootstrapMethod bootstrapMethod) {
+ String className = Type.getInternalName(bootstrapMethod.enclosingType());
+ String methodName = bootstrapMethod.name();
String methodType =
MethodType.methodType(
- methodHandle.returnType(), methodHandle.argumentTypes())
+ bootstrapMethod.returnType(),
+ bootstrapMethod.parameterTypes())
.toMethodDescriptorString();
return new Handle(
- handleKind, className, methodName, methodType, false /* itf */);
+ Opcodes.H_INVOKESTATIC,
+ className,
+ methodName,
+ methodType,
+ false /* itf */);
}
private Object decodeConstant(int index, Constant constant) {
@@ -211,11 +152,10 @@ class IndyTransformer {
}
}
- private Object[] buildBootstrapArguments(CalledByIndy callsite) {
- Constant[] rawArgs = callsite.methodHandleExtraArgs();
- Object[] args = new Object[rawArgs.length];
- for (int i = 0; i < rawArgs.length; ++i) {
- args[i] = decodeConstant(i, rawArgs[i]);
+ private Object[] buildBootstrapArguments(Constant[] bootstrapMethodArguments) {
+ Object[] args = new Object[bootstrapMethodArguments.length];
+ for (int i = 0; i < bootstrapMethodArguments.length; ++i) {
+ args[i] = decodeConstant(i, bootstrapMethodArguments[i]);
}
return args;
}
@@ -237,8 +177,8 @@ class IndyTransformer {
if (calledByIndy == null) {
continue;
}
- if (calledByIndy.name() == null) {
- throw new Error("CallByIndy annotation does not specify name");
+ if (calledByIndy.fieldOrMethodName() == null) {
+ throw new Error("CallByIndy annotation does not specify a field or method name");
}
final int PRIVATE_STATIC = Modifier.STATIC | Modifier.PRIVATE;
if ((m.getModifiers() & PRIVATE_STATIC) != PRIVATE_STATIC) {