diff options
| -rw-r--r-- | runtime/class_linker.cc | 3 | ||||
| -rw-r--r-- | runtime/mirror/method_type.cc | 27 | ||||
| -rw-r--r-- | runtime/transaction_test.cc | 13 | ||||
| -rw-r--r-- | runtime/well_known_classes.cc | 11 | ||||
| -rw-r--r-- | runtime/well_known_classes.h | 1 | ||||
| -rw-r--r-- | test/2265-const-method-type-cached/build.py | 19 | ||||
| -rw-r--r-- | test/2265-const-method-type-cached/expected-stderr.txt | 0 | ||||
| -rw-r--r-- | test/2265-const-method-type-cached/expected-stdout.txt | 0 | ||||
| -rwxr-xr-x | test/2265-const-method-type-cached/generate-sources | 29 | ||||
| -rw-r--r-- | test/2265-const-method-type-cached/info.txt | 3 | ||||
| -rwxr-xr-x | test/2265-const-method-type-cached/javac_post.sh | 30 | ||||
| -rw-r--r-- | test/2265-const-method-type-cached/src-util/annotations/ConstantMethodType.java | 34 | ||||
| -rw-r--r-- | test/2265-const-method-type-cached/src-util/transformer/ConstantTransformer.java | 157 | ||||
| -rw-r--r-- | test/2265-const-method-type-cached/src/Main.java | 105 | ||||
| -rwxr-xr-x | test/run_test_build.py | 1 |
15 files changed, 22 insertions, 411 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 2c22a906da..5489c0af6d 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -1191,9 +1191,8 @@ void ClassLinker::RunRootClinits(Thread* self) { WellKnownClasses::java_lang_reflect_InvocationTargetException_init, // Ensure `Parameter` class is initialized (avoid check at runtime). WellKnownClasses::java_lang_reflect_Parameter_init, - // Ensure `MethodHandles` and `MethodType` classes are initialized (avoid check at runtime). + // Ensure `MethodHandles` class is initialized (avoid check at runtime). WellKnownClasses::java_lang_invoke_MethodHandles_lookup, - WellKnownClasses::java_lang_invoke_MethodType_makeImpl, // Ensure `DirectByteBuffer` class is initialized (avoid check at runtime). WellKnownClasses::java_nio_DirectByteBuffer_init, // Ensure `FloatingDecimal` class is initialized (avoid check at runtime). diff --git a/runtime/mirror/method_type.cc b/runtime/mirror/method_type.cc index e58a6fbb06..ccc2b9d679 100644 --- a/runtime/mirror/method_type.cc +++ b/runtime/mirror/method_type.cc @@ -22,7 +22,6 @@ #include "obj_ptr-inl.h" #include "object_array-alloc-inl.h" #include "object_array-inl.h" -#include "well_known_classes.h" namespace art { namespace mirror { @@ -40,17 +39,29 @@ ObjPtr<ObjectArray<Class>> AllocatePTypesArray(Thread* self, int count) ObjPtr<MethodType> MethodType::Create(Thread* const self, Handle<Class> return_type, Handle<ObjectArray<Class>> parameter_types) { - ArtMethod* make_impl = WellKnownClasses::java_lang_invoke_MethodType_makeImpl; + StackHandleScope<1> hs(self); + Handle<MethodType> mt( + hs.NewHandle(ObjPtr<MethodType>::DownCast(GetClassRoot<MethodType>()->AllocObject(self)))); - const bool is_trusted = true; - ObjPtr<MethodType> mt = ObjPtr<MethodType>::DownCast(make_impl->InvokeStatic<'L', 'L', 'L', 'Z'>( - self, return_type.Get(), parameter_types.Get(), is_trusted)); - - if (self->IsExceptionPending()) { + if (mt == nullptr) { + self->AssertPendingOOMException(); return nullptr; } - return mt; + // We're initializing a newly allocated object, so we do not need to record that under + // a transaction. If the transaction is aborted, the whole object shall be unreachable. + mt->SetFieldObject</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>( + FormOffset(), nullptr); + mt->SetFieldObject</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>( + MethodDescriptorOffset(), nullptr); + mt->SetFieldObject</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>( + RTypeOffset(), return_type.Get()); + mt->SetFieldObject</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>( + PTypesOffset(), parameter_types.Get()); + mt->SetFieldObject</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>( + WrapAltOffset(), nullptr); + + return mt.Get(); } ObjPtr<MethodType> MethodType::CloneWithoutLeadingParameter(Thread* const self, diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc index 18e6403b59..04aa7cdb52 100644 --- a/runtime/transaction_test.cc +++ b/runtime/transaction_test.cc @@ -530,19 +530,8 @@ TEST_F(TransactionTest, ResolveString) { ASSERT_FALSE(soa.Self()->IsExceptionPending()); } -class MethodTypeTransactionTest : public TransactionTest { - protected: - MethodTypeTransactionTest() { - // java.lang.invoke.MethodType factory methods and mirror::MethodType::Create - // are backed by the same cache, which is in the primary boot image. As as a - // result, MethodType creation can lead to writes to the map under a - // transaction, which is forbidden. - this->use_boot_image_ = false; - } -}; - // Tests rolling back resolved method types in dex cache. -TEST_F(MethodTypeTransactionTest, ResolveMethodType) { +TEST_F(TransactionTest, ResolveMethodType) { ScopedObjectAccess soa(Thread::Current()); StackHandleScope<3> hs(soa.Self()); Handle<mirror::ClassLoader> class_loader( diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc index 0069219785..780fa830b8 100644 --- a/runtime/well_known_classes.cc +++ b/runtime/well_known_classes.cc @@ -97,7 +97,6 @@ ArtMethod* WellKnownClasses::java_lang_invoke_MethodHandle_asType; ArtMethod* WellKnownClasses::java_lang_invoke_MethodHandle_invokeExact; ArtMethod* WellKnownClasses::java_lang_invoke_MethodHandles_lookup; ArtMethod* WellKnownClasses::java_lang_invoke_MethodHandles_Lookup_findConstructor; -ArtMethod* WellKnownClasses::java_lang_invoke_MethodType_makeImpl; ArtMethod* WellKnownClasses::java_lang_ref_FinalizerReference_add; ArtMethod* WellKnownClasses::java_lang_ref_ReferenceQueue_add; ArtMethod* WellKnownClasses::java_lang_reflect_InvocationTargetException_init; @@ -362,7 +361,7 @@ void WellKnownClasses::InitFieldsAndMethodsOnly(JNIEnv* env) { java_lang_Short_valueOf = CachePrimitiveBoxingMethod(class_linker, self, 'S', "Ljava/lang/Short;"); - StackHandleScope<43u> hs(self); + StackHandleScope<42u> hs(self); Handle<mirror::Class> d_s_bdcl = hs.NewHandle(FindSystemClass(class_linker, self, "Ldalvik/system/BaseDexClassLoader;")); Handle<mirror::Class> d_s_dlcl = @@ -413,8 +412,6 @@ void WellKnownClasses::InitFieldsAndMethodsOnly(JNIEnv* env) { hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/lang/invoke/MethodHandles;")); Handle<mirror::Class> j_l_i_MethodHandles_Lookup = hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/lang/invoke/MethodHandles$Lookup;")); - Handle<mirror::Class> j_l_i_MethodType = - hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/lang/invoke/MethodType;")); Handle<mirror::Class> j_l_r_fr = hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/lang/ref/FinalizerReference;")); Handle<mirror::Class> j_l_r_rq = @@ -585,12 +582,6 @@ void WellKnownClasses::InitFieldsAndMethodsOnly(JNIEnv* env) { "findConstructor", "(Ljava/lang/Class;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;", pointer_size); - java_lang_invoke_MethodType_makeImpl = CacheMethod( - j_l_i_MethodType.Get(), - /* is_static=*/ true, - "makeImpl", - "(Ljava/lang/Class;[Ljava/lang/Class;Z)Ljava/lang/invoke/MethodType;", - pointer_size); java_lang_ref_FinalizerReference_add = CacheMethod( j_l_r_fr.Get(), /*is_static=*/ true, "add", "(Ljava/lang/Object;)V", pointer_size); diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h index a1cd7c53f1..cc6347cd5e 100644 --- a/runtime/well_known_classes.h +++ b/runtime/well_known_classes.h @@ -142,7 +142,6 @@ struct WellKnownClasses { static ArtMethod* java_lang_invoke_MethodHandle_invokeExact; static ArtMethod* java_lang_invoke_MethodHandles_lookup; static ArtMethod* java_lang_invoke_MethodHandles_Lookup_findConstructor; - static ArtMethod* java_lang_invoke_MethodType_makeImpl; static ArtMethod* java_lang_ref_FinalizerReference_add; static ArtMethod* java_lang_ref_ReferenceQueue_add; static ArtMethod* java_lang_reflect_InvocationTargetException_init; diff --git a/test/2265-const-method-type-cached/build.py b/test/2265-const-method-type-cached/build.py deleted file mode 100644 index 534952458e..0000000000 --- a/test/2265-const-method-type-cached/build.py +++ /dev/null @@ -1,19 +0,0 @@ -# -# Copyright (C) 2023 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. - - -def build(ctx): - ctx.bash("./generate-sources") - ctx.default_build(api_level="const-method-type") diff --git a/test/2265-const-method-type-cached/expected-stderr.txt b/test/2265-const-method-type-cached/expected-stderr.txt deleted file mode 100644 index e69de29bb2..0000000000 --- a/test/2265-const-method-type-cached/expected-stderr.txt +++ /dev/null diff --git a/test/2265-const-method-type-cached/expected-stdout.txt b/test/2265-const-method-type-cached/expected-stdout.txt deleted file mode 100644 index e69de29bb2..0000000000 --- a/test/2265-const-method-type-cached/expected-stdout.txt +++ /dev/null diff --git a/test/2265-const-method-type-cached/generate-sources b/test/2265-const-method-type-cached/generate-sources deleted file mode 100755 index 85448d47da..0000000000 --- a/test/2265-const-method-type-cached/generate-sources +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -# -# Copyright 2023 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. - -# make us exit on a failure -set -e - -export ASM_JAR="${ANDROID_BUILD_TOP}/prebuilts/misc/common/asm/asm-9.2.jar" - -# Build the transformer to apply to compiled classes. -mkdir classes -${JAVAC:-javac} ${JAVAC_ARGS} -cp "${ASM_JAR}" -d classes $(find src-util -name '*.java') -${SOONG_ZIP} --jar -o transformer.jar -C classes -D classes -rm -rf classes - -# Add annotation src files to our compiler inputs. -cp -r src-util/annotations src/ diff --git a/test/2265-const-method-type-cached/info.txt b/test/2265-const-method-type-cached/info.txt deleted file mode 100644 index ad09993559..0000000000 --- a/test/2265-const-method-type-cached/info.txt +++ /dev/null @@ -1,3 +0,0 @@ -const-method-type and MethodType factory methods should use the same intern -mechanism and return the same object when equal return and parameter types are -passed. diff --git a/test/2265-const-method-type-cached/javac_post.sh b/test/2265-const-method-type-cached/javac_post.sh deleted file mode 100755 index cd62e69137..0000000000 --- a/test/2265-const-method-type-cached/javac_post.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2023 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. - -set -e - -export ASM_JAR="${ANDROID_BUILD_TOP}/prebuilts/misc/common/asm/asm-9.2.jar" - -# Move original classes to intermediate location. -mv classes intermediate-classes -mkdir classes - -# Transform intermediate classes. -transformer_args="-cp ${ASM_JAR}:$PWD/transformer.jar transformer.ConstantTransformer" -for class in intermediate-classes/*.class ; do - transformed_class=classes/$(basename ${class}) - ${JAVA:-java} ${transformer_args} ${class} ${transformed_class} -done diff --git a/test/2265-const-method-type-cached/src-util/annotations/ConstantMethodType.java b/test/2265-const-method-type-cached/src-util/annotations/ConstantMethodType.java deleted file mode 100644 index 354cd3e661..0000000000 --- a/test/2265-const-method-type-cached/src-util/annotations/ConstantMethodType.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2023 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; - -/** - * Methods annotated with this annotation will be replaced with ldc bytecode - * with the MethodType described by the annotation. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface ConstantMethodType { - Class<?> returnType() default void.class; - - Class<?>[] parameterTypes() default {}; -}
\ No newline at end of file diff --git a/test/2265-const-method-type-cached/src-util/transformer/ConstantTransformer.java b/test/2265-const-method-type-cached/src-util/transformer/ConstantTransformer.java deleted file mode 100644 index 9eba5fd57c..0000000000 --- a/test/2265-const-method-type-cached/src-util/transformer/ConstantTransformer.java +++ /dev/null @@ -1,157 +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 transformer; - -import annotations.ConstantMethodType; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.invoke.MethodType; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.net.URL; -import java.net.URLClassLoader; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.Map; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.Handle; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -/** - * Replaces {@code ConstantMethodType} annotated methods with a load constant bytecode - * with a method type in the constant pool. - * - * Shamelessly copied from test/979-const-method-handle. - */ -public class ConstantTransformer { - - static class ConstantBuilder extends ClassVisitor { - private final Map<String, ConstantMethodType> constantMethodTypes; - - ConstantBuilder( - int api, - ClassVisitor cv, - Map<String, ConstantMethodType> constantMethodTypes) { - super(api, cv); - this.constantMethodTypes = constantMethodTypes; - } - - @Override - public MethodVisitor visitMethod( - int access, String name, String desc, String signature, String[] exceptions) { - MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); - return new MethodVisitor(this.api, mv) { - @Override - public void visitMethodInsn( - int opcode, String owner, String name, String desc, boolean itf) { - if (opcode == org.objectweb.asm.Opcodes.INVOKESTATIC) { - ConstantMethodType constantMethodType = constantMethodTypes.get(name); - if (constantMethodType != null) { - insertConstantMethodType(constantMethodType); - return; - } - } - mv.visitMethodInsn(opcode, owner, name, desc, itf); - } - - private Type buildMethodType(Class<?> returnType, Class<?>[] parameterTypes) { - Type rType = Type.getType(returnType); - Type[] pTypes = new Type[parameterTypes.length]; - for (int i = 0; i < pTypes.length; ++i) { - pTypes[i] = Type.getType(parameterTypes[i]); - } - return Type.getMethodType(rType, pTypes); - } - - private void insertConstantMethodType(ConstantMethodType constantMethodType) { - Type methodType = - buildMethodType( - constantMethodType.returnType(), - constantMethodType.parameterTypes()); - mv.visitLdcInsn(methodType); - } - }; - } - } - - private static void throwAnnotationError( - Method method, Class<?> annotationClass, String reason) { - StringBuilder sb = new StringBuilder(); - sb.append("Error in annotation ") - .append(annotationClass) - .append(" on method ") - .append(method) - .append(": ") - .append(reason); - throw new Error(sb.toString()); - } - - private static void checkMethodToBeReplaced( - Method method, Class<?> annotationClass, Class<?> returnType) { - final int PRIVATE_STATIC = Modifier.STATIC | Modifier.PRIVATE; - if ((method.getModifiers() & PRIVATE_STATIC) != PRIVATE_STATIC) { - throwAnnotationError(method, annotationClass, " method is not private and static"); - } - if (method.getTypeParameters().length != 0) { - throwAnnotationError(method, annotationClass, " method expects parameters"); - } - if (!method.getReturnType().equals(returnType)) { - throwAnnotationError(method, annotationClass, " wrong return type"); - } - } - - private static void transform(Path inputClassPath, Path outputClassPath) throws Throwable { - Path classLoadPath = inputClassPath.toAbsolutePath().getParent(); - URLClassLoader classLoader = - new URLClassLoader(new URL[] {classLoadPath.toUri().toURL()}, - ClassLoader.getSystemClassLoader()); - String inputClassName = inputClassPath.getFileName().toString().replace(".class", ""); - Class<?> inputClass = classLoader.loadClass(inputClassName); - - final Map<String, ConstantMethodType> constantMethodTypes = new HashMap<>(); - - for (Method m : inputClass.getDeclaredMethods()) { - ConstantMethodType constantMethodType = m.getAnnotation(ConstantMethodType.class); - if (constantMethodType != null) { - checkMethodToBeReplaced(m, ConstantMethodType.class, MethodType.class); - constantMethodTypes.put(m.getName(), constantMethodType); - continue; - } - } - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); - try (InputStream is = Files.newInputStream(inputClassPath)) { - ClassReader cr = new ClassReader(is); - ConstantBuilder cb = - new ConstantBuilder( - Opcodes.ASM7, cw, constantMethodTypes); - cr.accept(cb, 0); - } - try (OutputStream os = Files.newOutputStream(outputClassPath)) { - os.write(cw.toByteArray()); - } - } - - public static void main(String[] args) throws Throwable { - transform(Paths.get(args[0]), Paths.get(args[1])); - } -}
\ No newline at end of file diff --git a/test/2265-const-method-type-cached/src/Main.java b/test/2265-const-method-type-cached/src/Main.java deleted file mode 100644 index 51c3374e64..0000000000 --- a/test/2265-const-method-type-cached/src/Main.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2023 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.ConstantMethodType; - -import java.lang.invoke.MethodType; -import java.util.Objects; - -public class Main { - public static void main(String... args) throws Throwable { - testEquality(); - testNonEquality(); - } - - private static void unreachable() { - throw new Error("unreachable"); - } - - @ConstantMethodType( - returnType = void.class, - parameterTypes = { - boolean.class, - byte.class, - char.class, - short.class, - int.class, - long.class, - float.class, - double.class, - Object.class, - int[].class }) - private static MethodType takesEverythingReturnsVoid() { - unreachable(); - return null; - } - - public static void testEquality() throws Throwable { - MethodType actual = takesEverythingReturnsVoid(); - - MethodType expected = MethodType.methodType( - void.class, - boolean.class, - byte.class, - char.class, - short.class, - int.class, - long.class, - float.class, - double.class, - Object.class, - int[].class); - - assertSame(expected, actual); - } - - public static void testNonEquality() throws Throwable { - MethodType actual = takesEverythingReturnsVoid(); - - MethodType expected = MethodType.methodType( - boolean.class, - boolean.class, - byte.class, - char.class, - short.class, - int.class, - long.class, - float.class, - double.class, - Object.class, - int[].class); - - assertNotEqual(expected, actual); - } - - public static void assertNotEqual(Object expected, Object actual) { - if (Objects.equals(expected, actual)) { - String msg = "Expected to be non equal, but got: " + expected; - throw new AssertionError(msg); - } - } - - public static void assertSame(Object expected, Object actual) { - if (actual != expected) { - String msg = String.format("Expected: %s(%X), got %s(%X)", - expected, - System.identityHashCode(expected), - actual, - System.identityHashCode(actual)); - throw new AssertionError(msg); - } - } -}
\ No newline at end of file diff --git a/test/run_test_build.py b/test/run_test_build.py index 61b3bd06fe..c5b76c23f1 100755 --- a/test/run_test_build.py +++ b/test/run_test_build.py @@ -241,7 +241,6 @@ class BuildTestContext: "agents": 26, "method-handles": 26, "var-handles": 28, - "const-method-type": 28, } api_level = API_LEVEL[api_level] assert isinstance(api_level, int), api_level |