xref: /aosp_15_r20/art/runtime/art_method_test.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2022 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include <type_traits>
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include "art_method-alloc-inl.h"
20*795d594fSAndroid Build Coastguard Worker 
21*795d594fSAndroid Build Coastguard Worker #include "base/casts.h"
22*795d594fSAndroid Build Coastguard Worker #include "common_runtime_test.h"
23*795d594fSAndroid Build Coastguard Worker #include "mirror/class-alloc-inl.h"
24*795d594fSAndroid Build Coastguard Worker #include "well_known_classes.h"
25*795d594fSAndroid Build Coastguard Worker 
26*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
27*795d594fSAndroid Build Coastguard Worker 
28*795d594fSAndroid Build Coastguard Worker namespace {
29*795d594fSAndroid Build Coastguard Worker // Helper function to avoid `ASSERT_EQ` with floating point types.
ToIntegralType(float value)30*795d594fSAndroid Build Coastguard Worker int32_t ToIntegralType(float value) { return bit_cast<int32_t>(value); }
ToIntegralType(double value)31*795d594fSAndroid Build Coastguard Worker int64_t ToIntegralType(double value) { return bit_cast<int64_t>(value); }
ToIntegralType(T value)32*795d594fSAndroid Build Coastguard Worker template <typename T> T ToIntegralType(T value) { return value; }
33*795d594fSAndroid Build Coastguard Worker }
34*795d594fSAndroid Build Coastguard Worker 
35*795d594fSAndroid Build Coastguard Worker class ArtMethodTest : public CommonRuntimeTest {
36*795d594fSAndroid Build Coastguard Worker  protected:
ArtMethodTest()37*795d594fSAndroid Build Coastguard Worker   ArtMethodTest() {
38*795d594fSAndroid Build Coastguard Worker     use_boot_image_ = true;  // Make the Runtime creation cheaper.
39*795d594fSAndroid Build Coastguard Worker   }
40*795d594fSAndroid Build Coastguard Worker 
41*795d594fSAndroid Build Coastguard Worker   // Test primitive type boxing and unboxing.
42*795d594fSAndroid Build Coastguard Worker   //
43*795d594fSAndroid Build Coastguard Worker   // This provides basic checks that the translation of the compile-time shorty
44*795d594fSAndroid Build Coastguard Worker   // to argument types and return type are correct and that values are passed
45*795d594fSAndroid Build Coastguard Worker   // correctly for these single-argument calls (`ArtMethod::InvokeStatic()` with
46*795d594fSAndroid Build Coastguard Worker   // primitive args and `ArtMethod::InvokeInstance()` with a reference arg).
47*795d594fSAndroid Build Coastguard Worker   template <typename Type, char kPrimitive>
TestBoxUnbox(ArtMethod * value_of,const char * unbox_name,Type value)48*795d594fSAndroid Build Coastguard Worker   void TestBoxUnbox(ArtMethod* value_of, const char* unbox_name, Type value) {
49*795d594fSAndroid Build Coastguard Worker     Thread* self = Thread::Current();
50*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(self);
51*795d594fSAndroid Build Coastguard Worker     ASSERT_STREQ(value_of->GetName(), "valueOf");
52*795d594fSAndroid Build Coastguard Worker     std::string unbox_signature = std::string("()") + kPrimitive;
53*795d594fSAndroid Build Coastguard Worker     ArtMethod* unbox_method = value_of->GetDeclaringClass()->FindClassMethod(
54*795d594fSAndroid Build Coastguard Worker         unbox_name, unbox_signature, kRuntimePointerSize);
55*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(unbox_method != nullptr);
56*795d594fSAndroid Build Coastguard Worker     ASSERT_FALSE(unbox_method->IsStatic());
57*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(value_of->GetDeclaringClass()->IsFinal());
58*795d594fSAndroid Build Coastguard Worker 
59*795d594fSAndroid Build Coastguard Worker     static_assert(std::is_same_v<ObjPtr<mirror::Object> (ArtMethod::*)(Thread*, Type),
60*795d594fSAndroid Build Coastguard Worker                                  decltype(&ArtMethod::InvokeStatic<'L', kPrimitive>)>);
61*795d594fSAndroid Build Coastguard Worker     StackHandleScope<1u> hs(self);
62*795d594fSAndroid Build Coastguard Worker     Handle<mirror::Object> boxed =
63*795d594fSAndroid Build Coastguard Worker         hs.NewHandle(value_of->InvokeStatic<'L', kPrimitive>(self, value));
64*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(boxed != nullptr);
65*795d594fSAndroid Build Coastguard Worker     ASSERT_OBJ_PTR_EQ(boxed->GetClass(), value_of->GetDeclaringClass());
66*795d594fSAndroid Build Coastguard Worker     static_assert(std::is_same_v<Type (ArtMethod::*)(Thread*, ObjPtr<mirror::Object>),
67*795d594fSAndroid Build Coastguard Worker                                  decltype(&ArtMethod::InvokeInstance<kPrimitive>)>);
68*795d594fSAndroid Build Coastguard Worker     // Exercise both `InvokeInstance()` and `InvokeFinal()` (boxing classes are final).
69*795d594fSAndroid Build Coastguard Worker     Type unboxed1 = unbox_method->InvokeInstance<kPrimitive>(self, boxed.Get());
70*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(ToIntegralType(value), ToIntegralType(unboxed1));
71*795d594fSAndroid Build Coastguard Worker     Type unboxed2 = unbox_method->InvokeFinal<kPrimitive>(self, boxed.Get());
72*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(ToIntegralType(value), ToIntegralType(unboxed2));
73*795d594fSAndroid Build Coastguard Worker   }
74*795d594fSAndroid Build Coastguard Worker };
75*795d594fSAndroid Build Coastguard Worker 
TEST_F(ArtMethodTest,BoxUnboxBoolean)76*795d594fSAndroid Build Coastguard Worker TEST_F(ArtMethodTest, BoxUnboxBoolean) {
77*795d594fSAndroid Build Coastguard Worker   TestBoxUnbox<bool, 'Z'>(WellKnownClasses::java_lang_Boolean_valueOf, "booleanValue", true);
78*795d594fSAndroid Build Coastguard Worker }
79*795d594fSAndroid Build Coastguard Worker 
TEST_F(ArtMethodTest,BoxUnboxByte)80*795d594fSAndroid Build Coastguard Worker TEST_F(ArtMethodTest, BoxUnboxByte) {
81*795d594fSAndroid Build Coastguard Worker   TestBoxUnbox<int8_t, 'B'>(WellKnownClasses::java_lang_Byte_valueOf, "byteValue", -12);
82*795d594fSAndroid Build Coastguard Worker }
83*795d594fSAndroid Build Coastguard Worker 
TEST_F(ArtMethodTest,BoxUnboxChar)84*795d594fSAndroid Build Coastguard Worker TEST_F(ArtMethodTest, BoxUnboxChar) {
85*795d594fSAndroid Build Coastguard Worker   TestBoxUnbox<uint16_t, 'C'>(WellKnownClasses::java_lang_Character_valueOf, "charValue", 0xffaa);
86*795d594fSAndroid Build Coastguard Worker }
87*795d594fSAndroid Build Coastguard Worker 
TEST_F(ArtMethodTest,BoxUnboxShort)88*795d594fSAndroid Build Coastguard Worker TEST_F(ArtMethodTest, BoxUnboxShort) {
89*795d594fSAndroid Build Coastguard Worker   TestBoxUnbox<int16_t, 'S'>(WellKnownClasses::java_lang_Short_valueOf, "shortValue", -0x1234);
90*795d594fSAndroid Build Coastguard Worker }
91*795d594fSAndroid Build Coastguard Worker 
TEST_F(ArtMethodTest,BoxUnboxInt)92*795d594fSAndroid Build Coastguard Worker TEST_F(ArtMethodTest, BoxUnboxInt) {
93*795d594fSAndroid Build Coastguard Worker   TestBoxUnbox<int32_t, 'I'>(WellKnownClasses::java_lang_Integer_valueOf, "intValue", -0x12345678);
94*795d594fSAndroid Build Coastguard Worker }
95*795d594fSAndroid Build Coastguard Worker 
TEST_F(ArtMethodTest,BoxUnboxLong)96*795d594fSAndroid Build Coastguard Worker TEST_F(ArtMethodTest, BoxUnboxLong) {
97*795d594fSAndroid Build Coastguard Worker   TestBoxUnbox<int64_t, 'J'>(
98*795d594fSAndroid Build Coastguard Worker       WellKnownClasses::java_lang_Long_valueOf, "longValue", UINT64_C(-0x1234567887654321));
99*795d594fSAndroid Build Coastguard Worker }
100*795d594fSAndroid Build Coastguard Worker 
TEST_F(ArtMethodTest,BoxUnboxFloat)101*795d594fSAndroid Build Coastguard Worker TEST_F(ArtMethodTest, BoxUnboxFloat) {
102*795d594fSAndroid Build Coastguard Worker   TestBoxUnbox<float, 'F'>(WellKnownClasses::java_lang_Float_valueOf, "floatValue", -2.0f);
103*795d594fSAndroid Build Coastguard Worker }
104*795d594fSAndroid Build Coastguard Worker 
TEST_F(ArtMethodTest,BoxUnboxDouble)105*795d594fSAndroid Build Coastguard Worker TEST_F(ArtMethodTest, BoxUnboxDouble) {
106*795d594fSAndroid Build Coastguard Worker   TestBoxUnbox<double, 'D'>(WellKnownClasses::java_lang_Double_valueOf, "doubleValue", 8.0);
107*795d594fSAndroid Build Coastguard Worker }
108*795d594fSAndroid Build Coastguard Worker 
TEST_F(ArtMethodTest,ArrayList)109*795d594fSAndroid Build Coastguard Worker TEST_F(ArtMethodTest, ArrayList) {
110*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
111*795d594fSAndroid Build Coastguard Worker   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
112*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(self);
113*795d594fSAndroid Build Coastguard Worker   StackHandleScope<4u> hs(self);
114*795d594fSAndroid Build Coastguard Worker   Handle<mirror::Class> list_class =
115*795d594fSAndroid Build Coastguard Worker       hs.NewHandle(class_linker->FindSystemClass(self, "Ljava/util/List;"));
116*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(list_class != nullptr);
117*795d594fSAndroid Build Coastguard Worker   Handle<mirror::Class> abstract_list_class =
118*795d594fSAndroid Build Coastguard Worker       hs.NewHandle(class_linker->FindSystemClass(self, "Ljava/util/AbstractList;"));
119*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(abstract_list_class != nullptr);
120*795d594fSAndroid Build Coastguard Worker   Handle<mirror::Class> array_list_class =
121*795d594fSAndroid Build Coastguard Worker       hs.NewHandle(class_linker->FindSystemClass(self, "Ljava/util/ArrayList;"));
122*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(array_list_class != nullptr);
123*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(abstract_list_class->Implements(list_class.Get()));
124*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(array_list_class->IsSubClass(abstract_list_class.Get()));
125*795d594fSAndroid Build Coastguard Worker 
126*795d594fSAndroid Build Coastguard Worker   ArtMethod* init = array_list_class->FindClassMethod("<init>", "()V", kRuntimePointerSize);
127*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(init != nullptr);
128*795d594fSAndroid Build Coastguard Worker   ArtMethod* array_list_size_method =
129*795d594fSAndroid Build Coastguard Worker       array_list_class->FindClassMethod("size", "()I", kRuntimePointerSize);
130*795d594fSAndroid Build Coastguard Worker   DCHECK(array_list_size_method != nullptr);
131*795d594fSAndroid Build Coastguard Worker   ArtMethod* abstract_list_size_method =
132*795d594fSAndroid Build Coastguard Worker       abstract_list_class->FindClassMethod("size", "()I", kRuntimePointerSize);
133*795d594fSAndroid Build Coastguard Worker   DCHECK(abstract_list_size_method != nullptr);
134*795d594fSAndroid Build Coastguard Worker   ArtMethod* list_size_method =
135*795d594fSAndroid Build Coastguard Worker       list_class->FindInterfaceMethod("size", "()I", kRuntimePointerSize);
136*795d594fSAndroid Build Coastguard Worker   DCHECK(list_size_method != nullptr);
137*795d594fSAndroid Build Coastguard Worker 
138*795d594fSAndroid Build Coastguard Worker   Handle<mirror::Object> array_list = init->NewObject<>(hs, self);
139*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(self->IsExceptionPending());
140*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(array_list != nullptr);
141*795d594fSAndroid Build Coastguard Worker 
142*795d594fSAndroid Build Coastguard Worker   // Invoke `ArrayList.size()` directly, with virtual dispatch from
143*795d594fSAndroid Build Coastguard Worker   // `AbstractList.size()` and with interface dispatch from `List.size()`.
144*795d594fSAndroid Build Coastguard Worker   int32_t size = array_list_size_method->InvokeInstance<'I'>(self, array_list.Get());
145*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(self->IsExceptionPending());
146*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(0, size);
147*795d594fSAndroid Build Coastguard Worker   size = abstract_list_size_method->InvokeVirtual<'I'>(self, array_list.Get());
148*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(self->IsExceptionPending());
149*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(0, size);
150*795d594fSAndroid Build Coastguard Worker   size = list_size_method->InvokeInterface<'I'>(self, array_list.Get());
151*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(self->IsExceptionPending());
152*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(0, size);
153*795d594fSAndroid Build Coastguard Worker 
154*795d594fSAndroid Build Coastguard Worker   // Try to invoke abstract method `AbstractList.size()` directly.
155*795d594fSAndroid Build Coastguard Worker   abstract_list_size_method->InvokeInstance<'I'>(self, array_list.Get());
156*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(self->IsExceptionPending());
157*795d594fSAndroid Build Coastguard Worker   self->ClearException();
158*795d594fSAndroid Build Coastguard Worker }
159*795d594fSAndroid Build Coastguard Worker 
160*795d594fSAndroid Build Coastguard Worker }  // namespace art
161