class_linker-inl.h revision cb6b0f31ede2275e79e6199ec391147585a37a2a
1/*
2 * Copyright (C) 2011 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_CLASS_LINKER_INL_H_
18#define ART_RUNTIME_CLASS_LINKER_INL_H_
19
20#include "class_linker.h"
21#include "gc_root-inl.h"
22#include "gc/heap-inl.h"
23#include "mirror/art_field.h"
24#include "mirror/class_loader.h"
25#include "mirror/dex_cache-inl.h"
26#include "mirror/iftable.h"
27#include "mirror/object_array.h"
28#include "handle_scope-inl.h"
29
30namespace art {
31
32inline bool ClassLinker::IsInBootClassPath(const char* descriptor) {
33  DexFile::ClassPathEntry pair = DexFile::FindInClassPath(descriptor, boot_class_path_);
34  return pair.second != nullptr;
35}
36
37inline mirror::Class* ClassLinker::FindSystemClass(Thread* self, const char* descriptor) {
38  return FindClass(self, descriptor, NullHandle<mirror::ClassLoader>());
39}
40
41inline mirror::Class* ClassLinker::FindArrayClass(Thread* self, mirror::Class** element_class) {
42  for (size_t i = 0; i < kFindArrayCacheSize; ++i) {
43    // Read the cached array class once to avoid races with other threads setting it.
44    mirror::Class* array_class = find_array_class_cache_[i].Read();
45    if (array_class != nullptr && array_class->GetComponentType() == *element_class) {
46      return array_class;
47    }
48  }
49  DCHECK(!(*element_class)->IsPrimitiveVoid());
50  std::string descriptor = "[";
51  std::string temp;
52  descriptor += (*element_class)->GetDescriptor(&temp);
53  StackHandleScope<2> hs(Thread::Current());
54  Handle<mirror::ClassLoader> class_loader(hs.NewHandle((*element_class)->GetClassLoader()));
55  HandleWrapper<mirror::Class> h_element_class(hs.NewHandleWrapper(element_class));
56  mirror::Class* array_class = FindClass(self, descriptor.c_str(), class_loader);
57  // Benign races in storing array class and incrementing index.
58  size_t victim_index = find_array_class_cache_next_victim_;
59  find_array_class_cache_[victim_index] = GcRoot<mirror::Class>(array_class);
60  find_array_class_cache_next_victim_ = (victim_index + 1) % kFindArrayCacheSize;
61  return array_class;
62}
63
64inline mirror::String* ClassLinker::ResolveString(uint32_t string_idx,
65                                                  mirror::ArtMethod* referrer) {
66  mirror::String* resolved_string = referrer->GetDexCacheStrings()->Get(string_idx);
67  if (UNLIKELY(resolved_string == NULL)) {
68    mirror::Class* declaring_class = referrer->GetDeclaringClass();
69    StackHandleScope<1> hs(Thread::Current());
70    Handle<mirror::DexCache> dex_cache(hs.NewHandle(declaring_class->GetDexCache()));
71    const DexFile& dex_file = *dex_cache->GetDexFile();
72    resolved_string = ResolveString(dex_file, string_idx, dex_cache);
73    if (resolved_string != nullptr) {
74      DCHECK_EQ(dex_cache->GetResolvedString(string_idx), resolved_string);
75    }
76  }
77  return resolved_string;
78}
79
80inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx,
81                                               mirror::ArtMethod* referrer) {
82  mirror::Class* resolved_type = referrer->GetDexCacheResolvedType(type_idx);
83  if (UNLIKELY(resolved_type == nullptr)) {
84    mirror::Class* declaring_class = referrer->GetDeclaringClass();
85    StackHandleScope<2> hs(Thread::Current());
86    Handle<mirror::DexCache> dex_cache(hs.NewHandle(declaring_class->GetDexCache()));
87    Handle<mirror::ClassLoader> class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
88    const DexFile& dex_file = *dex_cache->GetDexFile();
89    resolved_type = ResolveType(dex_file, type_idx, dex_cache, class_loader);
90    // Note: We cannot check here to see whether we added the type to the cache. The type
91    //       might be an erroneous class, which results in it being hidden from us.
92  }
93  return resolved_type;
94}
95
96inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, mirror::ArtField* referrer) {
97  mirror::Class* declaring_class = referrer->GetDeclaringClass();
98  mirror::DexCache* dex_cache_ptr = declaring_class->GetDexCache();
99  mirror::Class* resolved_type = dex_cache_ptr->GetResolvedType(type_idx);
100  if (UNLIKELY(resolved_type == NULL)) {
101    StackHandleScope<2> hs(Thread::Current());
102    Handle<mirror::DexCache> dex_cache(hs.NewHandle(dex_cache_ptr));
103    Handle<mirror::ClassLoader> class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
104    const DexFile& dex_file = *dex_cache->GetDexFile();
105    resolved_type = ResolveType(dex_file, type_idx, dex_cache, class_loader);
106    // Note: We cannot check here to see whether we added the type to the cache. The type
107    //       might be an erroneous class, which results in it being hidden from us.
108  }
109  return resolved_type;
110}
111
112inline mirror::ArtMethod* ClassLinker::GetResolvedMethod(uint32_t method_idx,
113                                                         mirror::ArtMethod* referrer,
114                                                         InvokeType type) {
115  mirror::ArtMethod* resolved_method = referrer->GetDexCacheResolvedMethod(method_idx);
116  if (resolved_method == nullptr || resolved_method->IsRuntimeMethod()) {
117    return nullptr;
118  }
119  return resolved_method;
120}
121
122inline mirror::ArtMethod* ClassLinker::ResolveMethod(Thread* self, uint32_t method_idx,
123                                                     mirror::ArtMethod** referrer,
124                                                     InvokeType type) {
125  mirror::ArtMethod* resolved_method = GetResolvedMethod(method_idx, *referrer, type);
126  if (LIKELY(resolved_method != nullptr)) {
127    return resolved_method;
128  }
129  mirror::Class* declaring_class = (*referrer)->GetDeclaringClass();
130  StackHandleScope<3> hs(self);
131  Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(declaring_class->GetDexCache()));
132  Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
133  HandleWrapper<mirror::ArtMethod> h_referrer(hs.NewHandleWrapper(referrer));
134  const DexFile* dex_file = h_dex_cache->GetDexFile();
135  resolved_method = ResolveMethod(*dex_file, method_idx, h_dex_cache, h_class_loader, h_referrer,
136                                  type);
137  // Note: We cannot check here to see whether we added the method to the cache. It
138  //       might be an erroneous class, which results in it being hidden from us.
139  return resolved_method;
140}
141
142inline mirror::ArtField* ClassLinker::GetResolvedField(uint32_t field_idx,
143                                                       mirror::Class* field_declaring_class) {
144  return field_declaring_class->GetDexCache()->GetResolvedField(field_idx);
145}
146
147inline mirror::ArtField* ClassLinker::ResolveField(uint32_t field_idx, mirror::ArtMethod* referrer,
148                                                   bool is_static) {
149  mirror::Class* declaring_class = referrer->GetDeclaringClass();
150  mirror::ArtField* resolved_field = GetResolvedField(field_idx, declaring_class);
151  if (UNLIKELY(resolved_field == NULL)) {
152    StackHandleScope<2> hs(Thread::Current());
153    Handle<mirror::DexCache> dex_cache(hs.NewHandle(declaring_class->GetDexCache()));
154    Handle<mirror::ClassLoader> class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
155    const DexFile& dex_file = *dex_cache->GetDexFile();
156    resolved_field = ResolveField(dex_file, field_idx, dex_cache, class_loader, is_static);
157    // Note: We cannot check here to see whether we added the field to the cache. The type
158    //       might be an erroneous class, which results in it being hidden from us.
159  }
160  return resolved_field;
161}
162
163template <class T>
164inline mirror::ObjectArray<T>* ClassLinker::AllocObjectArray(Thread* self, size_t length) {
165  return mirror::ObjectArray<T>::Alloc(self, GetClassRoot(kObjectArrayClass), length);
166}
167
168inline mirror::ObjectArray<mirror::Class>* ClassLinker::AllocClassArray(Thread* self,
169                                                                        size_t length) {
170  return mirror::ObjectArray<mirror::Class>::Alloc(self, GetClassRoot(kClassArrayClass), length);
171}
172
173inline mirror::ObjectArray<mirror::String>* ClassLinker::AllocStringArray(Thread* self,
174                                                                          size_t length) {
175  return mirror::ObjectArray<mirror::String>::Alloc(self, GetClassRoot(kJavaLangStringArrayClass),
176                                                    length);
177}
178
179inline mirror::ObjectArray<mirror::ArtMethod>* ClassLinker::AllocArtMethodArray(Thread* self,
180                                                                                size_t length) {
181  return mirror::ObjectArray<mirror::ArtMethod>::Alloc(self,
182      GetClassRoot(kJavaLangReflectArtMethodArrayClass), length);
183}
184
185inline mirror::IfTable* ClassLinker::AllocIfTable(Thread* self, size_t ifcount) {
186  return down_cast<mirror::IfTable*>(
187      mirror::IfTable::Alloc(self, GetClassRoot(kObjectArrayClass),
188                             ifcount * mirror::IfTable::kMax));
189}
190
191inline mirror::ObjectArray<mirror::ArtField>* ClassLinker::AllocArtFieldArray(Thread* self,
192                                                                              size_t length) {
193  gc::Heap* const heap = Runtime::Current()->GetHeap();
194  // Can't have movable field arrays for mark compact since we need these arrays to always be valid
195  // so that we can do Object::VisitReferences in the case where the fields don't fit in the
196  // reference offsets word.
197  return mirror::ObjectArray<mirror::ArtField>::Alloc(
198      self, GetClassRoot(kJavaLangReflectArtFieldArrayClass), length,
199      kMoveFieldArrays ? heap->GetCurrentAllocator() : heap->GetCurrentNonMovingAllocator());
200}
201
202inline mirror::Class* ClassLinker::GetClassRoot(ClassRoot class_root)
203    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
204  DCHECK(!class_roots_.IsNull());
205  mirror::ObjectArray<mirror::Class>* class_roots = class_roots_.Read();
206  mirror::Class* klass = class_roots->Get(class_root);
207  DCHECK(klass != NULL);
208  return klass;
209}
210
211inline mirror::DexCache* ClassLinker::GetDexCache(size_t idx) {
212  dex_lock_.AssertSharedHeld(Thread::Current());
213  DCHECK(idx < dex_caches_.size());
214  return dex_caches_[idx].Read();
215}
216
217}  // namespace art
218
219#endif  // ART_RUNTIME_CLASS_LINKER_INL_H_
220