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