blob: 4ac99673ee219a4baf660b6814c42ad600b32dd8 [file] [log] [blame]
Ian Rogers57b86d42012-03-27 16:05:41 -07001/*
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
Mathieu Chartiere401d142015-04-22 13:56:20 -070017#include "art_method-inl.h"
Andreas Gampe8228cdf2017-05-30 15:03:54 -070018#include "base/callee_save_type.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070019#include "callee_save_frame.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080020#include "class_linker-inl.h"
Vladimir Markoaad75c62016-10-03 08:46:48 +000021#include "class_table-inl.h"
Ian Rogersfa46d3e2013-05-15 00:16:04 -070022#include "dex_file-inl.h"
Andreas Gampea5b09a62016-11-17 15:21:22 -080023#include "dex_file_types.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070024#include "entrypoints/entrypoint_utils-inl.h"
Vladimir Markoaad75c62016-10-03 08:46:48 +000025#include "gc/heap.h"
26#include "mirror/class-inl.h"
27#include "mirror/class_loader.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070028#include "mirror/object-inl.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070029#include "mirror/object_array-inl.h"
Vladimir Markoaad75c62016-10-03 08:46:48 +000030#include "oat_file.h"
31#include "runtime.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070032
33namespace art {
34
Vladimir Markof3c52b42017-11-17 17:32:12 +000035static void StoreObjectInBss(ArtMethod* outer_method,
36 const OatFile* oat_file,
37 size_t bss_offset,
38 ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_) {
39 // Used for storing Class or String in .bss GC roots.
40 static_assert(sizeof(GcRoot<mirror::Class>) == sizeof(GcRoot<mirror::Object>), "Size check.");
41 static_assert(sizeof(GcRoot<mirror::String>) == sizeof(GcRoot<mirror::Object>), "Size check.");
42 DCHECK_NE(bss_offset, IndexBssMappingLookup::npos);
43 DCHECK_ALIGNED(bss_offset, sizeof(GcRoot<mirror::Object>));
44 GcRoot<mirror::Object>* slot = reinterpret_cast<GcRoot<mirror::Object>*>(
45 const_cast<uint8_t*>(oat_file->BssBegin() + bss_offset));
46 DCHECK_GE(slot, oat_file->GetBssGcRoots().data());
47 DCHECK_LT(slot, oat_file->GetBssGcRoots().data() + oat_file->GetBssGcRoots().size());
48 if (slot->IsNull()) {
49 // This may race with another thread trying to store the very same value but that's OK.
50 *slot = GcRoot<mirror::Object>(object);
51 // We need a write barrier for the class loader that holds the GC roots in the .bss.
Vladimir Marko9b03cb42017-02-16 16:37:03 +000052 ObjPtr<mirror::ClassLoader> class_loader = outer_method->GetClassLoader();
Vladimir Markof3c52b42017-11-17 17:32:12 +000053 Runtime* runtime = Runtime::Current();
Vladimir Marko9b03cb42017-02-16 16:37:03 +000054 if (kIsDebugBuild) {
Vladimir Markof3c52b42017-11-17 17:32:12 +000055 ClassTable* class_table = runtime->GetClassLinker()->ClassTableForClassLoader(class_loader);
56 CHECK(class_table != nullptr && !class_table->InsertOatFile(oat_file))
Vladimir Marko1998cd02017-01-13 13:02:58 +000057 << "Oat file with .bss GC roots was not registered in class table: "
Vladimir Markof3c52b42017-11-17 17:32:12 +000058 << oat_file->GetLocation();
Vladimir Marko9b03cb42017-02-16 16:37:03 +000059 }
Mathieu Chartiera1467d02017-02-22 09:22:50 -080060 if (class_loader != nullptr) {
Vladimir Markof3c52b42017-11-17 17:32:12 +000061 runtime->GetHeap()->WriteBarrierEveryFieldOf(class_loader);
Mathieu Chartiera1467d02017-02-22 09:22:50 -080062 } else {
Vladimir Markof3c52b42017-11-17 17:32:12 +000063 runtime->GetClassLinker()->WriteBarrierForBootOatFileBssRoots(oat_file);
64 }
65 } else {
66 // Each slot serves to store exactly one Class or String.
67 DCHECK_EQ(object, slot->Read());
68 }
69}
70
71static inline void StoreTypeInBss(ArtMethod* outer_method,
72 dex::TypeIndex type_idx,
73 ObjPtr<mirror::Class> resolved_type)
74 REQUIRES_SHARED(Locks::mutator_lock_) {
75 const DexFile* dex_file = outer_method->GetDexFile();
76 DCHECK(dex_file != nullptr);
77 const OatDexFile* oat_dex_file = dex_file->GetOatDexFile();
78 if (oat_dex_file != nullptr) {
79 size_t bss_offset = IndexBssMappingLookup::GetBssOffset(oat_dex_file->GetTypeBssMapping(),
80 type_idx.index_,
81 dex_file->NumTypeIds(),
82 sizeof(GcRoot<mirror::Class>));
83 if (bss_offset != IndexBssMappingLookup::npos) {
84 StoreObjectInBss(outer_method, oat_dex_file->GetOatFile(), bss_offset, resolved_type);
85 }
86 }
87}
88
89static inline void StoreStringInBss(ArtMethod* outer_method,
90 dex::StringIndex string_idx,
91 ObjPtr<mirror::String> resolved_string)
92 REQUIRES_SHARED(Locks::mutator_lock_) __attribute__((optnone)) {
93 const DexFile* dex_file = outer_method->GetDexFile();
94 DCHECK(dex_file != nullptr);
95 const OatDexFile* oat_dex_file = dex_file->GetOatDexFile();
96 if (oat_dex_file != nullptr) {
97 size_t bss_offset = IndexBssMappingLookup::GetBssOffset(oat_dex_file->GetStringBssMapping(),
98 string_idx.index_,
99 dex_file->NumStringIds(),
100 sizeof(GcRoot<mirror::Class>));
101 if (bss_offset != IndexBssMappingLookup::npos) {
102 StoreObjectInBss(outer_method, oat_dex_file->GetOatFile(), bss_offset, resolved_string);
Vladimir Marko1998cd02017-01-13 13:02:58 +0000103 }
Vladimir Marko6bec91c2017-01-09 15:03:12 +0000104 }
105}
106
Nicolas Geoffray7ea6a172015-05-19 18:58:54 +0100107extern "C" mirror::Class* artInitializeStaticStorageFromCode(uint32_t type_idx, Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700108 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogerse2645d32012-04-11 14:42:42 -0700109 // Called to ensure static storage base is initialized for direct static field reads and writes.
110 // A class may be accessing another class' fields when it doesn't have access, as access has been
111 // given by inheritance.
Ian Rogers1d8cdbc2014-09-22 22:51:09 -0700112 ScopedQuickEntrypointChecks sqec(self);
Mingyao Yang0a87a652017-04-12 13:43:15 -0700113 auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(
114 self, CalleeSaveType::kSaveEverythingForClinit);
Vladimir Marko6bec91c2017-01-09 15:03:12 +0000115 ArtMethod* caller = caller_and_outer.caller;
116 mirror::Class* result =
117 ResolveVerifyAndClinit(dex::TypeIndex(type_idx), caller, self, true, false);
118 if (LIKELY(result != nullptr)) {
Vladimir Markof3c52b42017-11-17 17:32:12 +0000119 StoreTypeInBss(caller_and_outer.outer_method, dex::TypeIndex(type_idx), result);
Vladimir Marko6bec91c2017-01-09 15:03:12 +0000120 }
121 return result;
Ian Rogers57b86d42012-03-27 16:05:41 -0700122}
123
Nicolas Geoffray7ea6a172015-05-19 18:58:54 +0100124extern "C" mirror::Class* artInitializeTypeFromCode(uint32_t type_idx, Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700125 REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Markof3c52b42017-11-17 17:32:12 +0000126 // Called when the .bss slot was empty or for main-path runtime call.
Ian Rogers1d8cdbc2014-09-22 22:51:09 -0700127 ScopedQuickEntrypointChecks sqec(self);
Mingyao Yang0a87a652017-04-12 13:43:15 -0700128 auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(
129 self, CalleeSaveType::kSaveEverythingForClinit);
Vladimir Marko6bec91c2017-01-09 15:03:12 +0000130 ArtMethod* caller = caller_and_outer.caller;
131 mirror::Class* result =
132 ResolveVerifyAndClinit(dex::TypeIndex(type_idx), caller, self, false, false);
133 if (LIKELY(result != nullptr)) {
Vladimir Markof3c52b42017-11-17 17:32:12 +0000134 StoreTypeInBss(caller_and_outer.outer_method, dex::TypeIndex(type_idx), result);
Vladimir Marko6bec91c2017-01-09 15:03:12 +0000135 }
136 return result;
Ian Rogers57b86d42012-03-27 16:05:41 -0700137}
138
Nicolas Geoffray7ea6a172015-05-19 18:58:54 +0100139extern "C" mirror::Class* artInitializeTypeAndVerifyAccessFromCode(uint32_t type_idx, Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700140 REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Markof3c52b42017-11-17 17:32:12 +0000141 // Called when caller isn't guaranteed to have access to a type.
Ian Rogers1d8cdbc2014-09-22 22:51:09 -0700142 ScopedQuickEntrypointChecks sqec(self);
Andreas Gampe8228cdf2017-05-30 15:03:54 -0700143 auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(self,
144 CalleeSaveType::kSaveEverything);
Vladimir Marko6bec91c2017-01-09 15:03:12 +0000145 ArtMethod* caller = caller_and_outer.caller;
146 mirror::Class* result =
147 ResolveVerifyAndClinit(dex::TypeIndex(type_idx), caller, self, false, true);
Vladimir Markof3c52b42017-11-17 17:32:12 +0000148 // Do not StoreTypeInBss(); access check entrypoint is never used together with .bss.
Vladimir Marko6bec91c2017-01-09 15:03:12 +0000149 return result;
Ian Rogers57b86d42012-03-27 16:05:41 -0700150}
151
Nicolas Geoffray7ea6a172015-05-19 18:58:54 +0100152extern "C" mirror::String* artResolveStringFromCode(int32_t string_idx, Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700153 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers1d8cdbc2014-09-22 22:51:09 -0700154 ScopedQuickEntrypointChecks sqec(self);
Andreas Gampe8228cdf2017-05-30 15:03:54 -0700155 auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(self,
156 CalleeSaveType::kSaveEverything);
Vladimir Marko6bec91c2017-01-09 15:03:12 +0000157 ArtMethod* caller = caller_and_outer.caller;
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800158 mirror::String* result = ResolveStringFromCode(caller, dex::StringIndex(string_idx));
Vladimir Markoaad75c62016-10-03 08:46:48 +0000159 if (LIKELY(result != nullptr)) {
Vladimir Markof3c52b42017-11-17 17:32:12 +0000160 StoreStringInBss(caller_and_outer.outer_method, dex::StringIndex(string_idx), result);
Vladimir Markoaad75c62016-10-03 08:46:48 +0000161 }
162 return result;
Ian Rogers57b86d42012-03-27 16:05:41 -0700163}
164
165} // namespace art