1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_RUNTIME_INTERPRETER_UNSTARTED_RUNTIME_TEST_H_
18 #define ART_RUNTIME_INTERPRETER_UNSTARTED_RUNTIME_TEST_H_
19 
20 #include "unstarted_runtime.h"
21 
22 #include <memory>
23 
24 #include "class_linker-inl.h"
25 #include "common_runtime_test.h"
26 #include "handle.h"
27 #include "handle_scope-inl.h"
28 #include "interpreter_common.h"
29 #include "mirror/object_array-alloc-inl.h"
30 #include "mirror/object_array-inl.h"
31 #include "shadow_frame-inl.h"
32 
33 namespace art HIDDEN {
34 namespace interpreter {
35 
36 // Deleter to be used with ShadowFrame::CreateDeoptimizedFrame objects.
37 struct DeoptShadowFrameDelete {
38   // NOTE: Deleting a const object is valid but free() takes a non-const pointer.
operatorDeoptShadowFrameDelete39   void operator()(ShadowFrame* ptr) const {
40     ShadowFrame::DeleteDeoptimizedFrame(ptr);
41   }
42 };
43 // Alias for std::unique_ptr<> that uses the above deleter.
44 using UniqueDeoptShadowFramePtr = std::unique_ptr<ShadowFrame, DeoptShadowFrameDelete>;
45 
46 class UnstartedRuntimeTestBase : public CommonRuntimeTest {
47  protected:
48   // Re-expose all UnstartedRuntime implementations so we don't need to declare a million
49   // test friends.
50 
51   // Methods that intercept available libcore implementations.
52 #define UNSTARTED_DIRECT(Name, DescriptorIgnored, NameIgnored, SignatureIgnored)              \
53   static void Unstarted ## Name(Thread* self,                                                 \
54                                 ShadowFrame* shadow_frame,                                    \
55                                 JValue* result,                                               \
56                                 size_t arg_offset)                                            \
57       REQUIRES_SHARED(Locks::mutator_lock_) {                                                 \
58     interpreter::UnstartedRuntime::Unstarted ## Name(self, shadow_frame, result, arg_offset); \
59   }
UNSTARTED_RUNTIME_DIRECT_LIST(UNSTARTED_DIRECT)60   UNSTARTED_RUNTIME_DIRECT_LIST(UNSTARTED_DIRECT)
61 #undef UNSTARTED_DIRECT
62 
63   // Methods that are native.
64 #define UNSTARTED_JNI(Name, DescriptorIgnored, NameIgnored, SignatureIgnored)                  \
65   static void UnstartedJNI ## Name(Thread* self,                                               \
66                                    ArtMethod* method,                                          \
67                                    mirror::Object* receiver,                                   \
68                                    uint32_t* args,                                             \
69                                    JValue* result)                                             \
70       REQUIRES_SHARED(Locks::mutator_lock_) {                                                  \
71     interpreter::UnstartedRuntime::UnstartedJNI ## Name(self, method, receiver, args, result); \
72   }
73   UNSTARTED_RUNTIME_JNI_LIST(UNSTARTED_JNI)
74 #undef UNSTARTED_JNI
75 
76   UniqueDeoptShadowFramePtr CreateShadowFrame(uint32_t num_vregs,
77                                               ArtMethod* method,
78                                               uint32_t dex_pc) {
79     return UniqueDeoptShadowFramePtr(
80         ShadowFrame::CreateDeoptimizedFrame(num_vregs, method, dex_pc));
81   }
82 
GetBootClassLoader()83   mirror::ClassLoader* GetBootClassLoader() REQUIRES_SHARED(Locks::mutator_lock_) {
84     Thread* self = Thread::Current();
85     StackHandleScope<2> hs(self);
86 
87     // Create the fake boot classloader. Any instance is fine, they are technically interchangeable.
88     Handle<mirror::Class> boot_cp_class = hs.NewHandle(class_linker_->FindClass(
89         self, "Ljava/lang/BootClassLoader;", ScopedNullHandle<mirror::ClassLoader>()));
90     CHECK(boot_cp_class != nullptr);
91     CHECK(class_linker_->EnsureInitialized(
92         self, boot_cp_class, /*can_init_fields=*/ true, /*can_init_parents=*/ true));
93 
94     Handle<mirror::ClassLoader> boot_cp =
95         hs.NewHandle(boot_cp_class->AllocObject(self)->AsClassLoader());
96     CHECK(boot_cp != nullptr);
97 
98     ArtMethod* boot_cp_init =
99         boot_cp_class->FindConstructor("()V", class_linker_->GetImagePointerSize());
100     CHECK(boot_cp_init != nullptr);
101 
102     JValue result;
103     UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, boot_cp_init, 0);
104     shadow_frame->SetVRegReference(0, boot_cp.Get());
105 
106     // create instruction data for invoke-direct {v0} of method with fake index
107     uint16_t inst_data[3] = { 0x1070, 0x0000, 0x0010 };
108 
109     interpreter::DoCall<false>(boot_cp_init,
110                                self,
111                                *shadow_frame,
112                                Instruction::At(inst_data),
113                                inst_data[0],
114                                /* string_init= */ false,
115                                &result);
116     CHECK(!self->IsExceptionPending());
117 
118     return boot_cp.Get();
119   }
120 };
121 
122 }  // namespace interpreter
123 }  // namespace art
124 
125 #endif  // ART_RUNTIME_INTERPRETER_UNSTARTED_RUNTIME_TEST_H_
126