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