1 /*
2  * Copyright (C) 2012 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 #include "art_method-inl.h"
18 #include "callee_save_frame.h"
19 #include "entrypoints/entrypoint_utils-inl.h"
20 #include "class_linker-inl.h"
21 #include "class_table-inl.h"
22 #include "dex_file-inl.h"
23 #include "dex_file_types.h"
24 #include "gc/heap.h"
25 #include "mirror/class-inl.h"
26 #include "mirror/class_loader.h"
27 #include "mirror/object_array-inl.h"
28 #include "mirror/object-inl.h"
29 #include "oat_file.h"
30 #include "runtime.h"
31 
32 namespace art {
33 
BssWriteBarrier(ArtMethod * outer_method)34 static inline void BssWriteBarrier(ArtMethod* outer_method) REQUIRES_SHARED(Locks::mutator_lock_) {
35   // For AOT code, we need a write barrier for the class loader that holds the
36   // GC roots in the .bss.
37   const DexFile* dex_file = outer_method->GetDexFile();
38   if (dex_file != nullptr &&
39       dex_file->GetOatDexFile() != nullptr &&
40       !dex_file->GetOatDexFile()->GetOatFile()->GetBssGcRoots().empty()) {
41     ObjPtr<mirror::ClassLoader> class_loader = outer_method->GetClassLoader();
42     if (kIsDebugBuild) {
43       ClassTable* class_table =
44           Runtime::Current()->GetClassLinker()->ClassTableForClassLoader(class_loader);
45       CHECK(class_table != nullptr &&
46             !class_table->InsertOatFile(dex_file->GetOatDexFile()->GetOatFile()))
47           << "Oat file with .bss GC roots was not registered in class table: "
48           << dex_file->GetOatDexFile()->GetOatFile()->GetLocation();
49     }
50     if (class_loader != nullptr) {
51       // Note that we emit the barrier before the compiled code stores the String or Class
52       // as a GC root. This is OK as there is no suspend point point in between.
53       Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader);
54     } else {
55       Runtime::Current()->GetClassLinker()->WriteBarrierForBootOatFileBssRoots(
56           dex_file->GetOatDexFile()->GetOatFile());
57     }
58   }
59 }
60 
61 constexpr Runtime::CalleeSaveType kInitEntrypointSaveType =
62     // TODO: Change allocation entrypoints on MIPS and MIPS64 to kSaveEverything.
63     (kRuntimeISA == kMips || kRuntimeISA == kMips64) ? Runtime::kSaveRefsOnly
64                                                      : Runtime::kSaveEverything;
65 
artInitializeStaticStorageFromCode(uint32_t type_idx,Thread * self)66 extern "C" mirror::Class* artInitializeStaticStorageFromCode(uint32_t type_idx, Thread* self)
67     REQUIRES_SHARED(Locks::mutator_lock_) {
68   // Called to ensure static storage base is initialized for direct static field reads and writes.
69   // A class may be accessing another class' fields when it doesn't have access, as access has been
70   // given by inheritance.
71   ScopedQuickEntrypointChecks sqec(self);
72   auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(self, kInitEntrypointSaveType);
73   ArtMethod* caller = caller_and_outer.caller;
74   mirror::Class* result =
75       ResolveVerifyAndClinit(dex::TypeIndex(type_idx), caller, self, true, false);
76   if (LIKELY(result != nullptr)) {
77     BssWriteBarrier(caller_and_outer.outer_method);
78   }
79   return result;
80 }
81 
artInitializeTypeFromCode(uint32_t type_idx,Thread * self)82 extern "C" mirror::Class* artInitializeTypeFromCode(uint32_t type_idx, Thread* self)
83     REQUIRES_SHARED(Locks::mutator_lock_) {
84   // Called when method->dex_cache_resolved_types_[] misses.
85   ScopedQuickEntrypointChecks sqec(self);
86   auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(self, kInitEntrypointSaveType);
87   ArtMethod* caller = caller_and_outer.caller;
88   mirror::Class* result =
89       ResolveVerifyAndClinit(dex::TypeIndex(type_idx), caller, self, false, false);
90   if (LIKELY(result != nullptr)) {
91     BssWriteBarrier(caller_and_outer.outer_method);
92   }
93   return result;
94 }
95 
artInitializeTypeAndVerifyAccessFromCode(uint32_t type_idx,Thread * self)96 extern "C" mirror::Class* artInitializeTypeAndVerifyAccessFromCode(uint32_t type_idx, Thread* self)
97     REQUIRES_SHARED(Locks::mutator_lock_) {
98   // Called when caller isn't guaranteed to have access to a type and the dex cache may be
99   // unpopulated.
100   ScopedQuickEntrypointChecks sqec(self);
101   auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(self, kInitEntrypointSaveType);
102   ArtMethod* caller = caller_and_outer.caller;
103   mirror::Class* result =
104       ResolveVerifyAndClinit(dex::TypeIndex(type_idx), caller, self, false, true);
105   if (LIKELY(result != nullptr)) {
106     BssWriteBarrier(caller_and_outer.outer_method);
107   }
108   return result;
109 }
110 
artResolveStringFromCode(int32_t string_idx,Thread * self)111 extern "C" mirror::String* artResolveStringFromCode(int32_t string_idx, Thread* self)
112     REQUIRES_SHARED(Locks::mutator_lock_) {
113   ScopedQuickEntrypointChecks sqec(self);
114   auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(self, kInitEntrypointSaveType);
115   ArtMethod* caller = caller_and_outer.caller;
116   mirror::String* result = ResolveStringFromCode(caller, dex::StringIndex(string_idx));
117   if (LIKELY(result != nullptr)) {
118     BssWriteBarrier(caller_and_outer.outer_method);
119   }
120   return result;
121 }
122 
123 }  // namespace art
124