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