1 /*
2 * Copyright (C) 2018 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 "intrinsic_objects.h"
18
19 #include "art_field-inl.h"
20 #include "base/casts.h"
21 #include "base/logging.h"
22 #include "image.h"
23 #include "obj_ptr-inl.h"
24
25 namespace art {
26
27 static constexpr size_t kIntrinsicObjectsOffset =
28 enum_cast<size_t>(ImageHeader::kIntrinsicObjectsStart);
29
LookupIntegerCache(Thread * self,ClassLinker * class_linker)30 ObjPtr<mirror::ObjectArray<mirror::Object>> IntrinsicObjects::LookupIntegerCache(
31 Thread* self, ClassLinker* class_linker) {
32 ObjPtr<mirror::Class> integer_cache_class = class_linker->LookupClass(
33 self, "Ljava/lang/Integer$IntegerCache;", /* class_loader= */ nullptr);
34 if (integer_cache_class == nullptr || !integer_cache_class->IsInitialized()) {
35 return nullptr;
36 }
37 ArtField* cache_field =
38 integer_cache_class->FindDeclaredStaticField("cache", "[Ljava/lang/Integer;");
39 CHECK(cache_field != nullptr);
40 ObjPtr<mirror::ObjectArray<mirror::Object>> integer_cache =
41 ObjPtr<mirror::ObjectArray<mirror::Object>>::DownCast(
42 cache_field->GetObject(integer_cache_class));
43 CHECK(integer_cache != nullptr);
44 return integer_cache;
45 }
46
HasIntrinsicObjects(ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects)47 static bool HasIntrinsicObjects(
48 ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects)
49 REQUIRES_SHARED(Locks::mutator_lock_) {
50 DCHECK(boot_image_live_objects != nullptr);
51 uint32_t length = static_cast<uint32_t>(boot_image_live_objects->GetLength());
52 DCHECK_GE(length, kIntrinsicObjectsOffset);
53 return length != kIntrinsicObjectsOffset;
54 }
55
GetIntegerValueOfCache(ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects)56 ObjPtr<mirror::ObjectArray<mirror::Object>> IntrinsicObjects::GetIntegerValueOfCache(
57 ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects) {
58 if (!HasIntrinsicObjects(boot_image_live_objects)) {
59 return nullptr; // No intrinsic objects.
60 }
61 // No need for read barrier for boot image object or for verifying the value that was just stored.
62 ObjPtr<mirror::Object> result =
63 boot_image_live_objects->GetWithoutChecks<kVerifyNone, kWithoutReadBarrier>(
64 kIntrinsicObjectsOffset);
65 DCHECK(result != nullptr);
66 DCHECK(result->IsObjectArray());
67 DCHECK(result->GetClass()->DescriptorEquals("[Ljava/lang/Integer;"));
68 return ObjPtr<mirror::ObjectArray<mirror::Object>>::DownCast(result);
69 }
70
GetIntegerValueOfObject(ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects,uint32_t index)71 ObjPtr<mirror::Object> IntrinsicObjects::GetIntegerValueOfObject(
72 ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects,
73 uint32_t index) {
74 DCHECK(HasIntrinsicObjects(boot_image_live_objects));
75 DCHECK_LT(index,
76 static_cast<uint32_t>(GetIntegerValueOfCache(boot_image_live_objects)->GetLength()));
77
78 // No need for read barrier for boot image object or for verifying the value that was just stored.
79 ObjPtr<mirror::Object> result =
80 boot_image_live_objects->GetWithoutChecks<kVerifyNone, kWithoutReadBarrier>(
81 kIntrinsicObjectsOffset + /* skip the IntegerCache.cache */ 1u + index);
82 DCHECK(result != nullptr);
83 DCHECK(result->GetClass()->DescriptorEquals("Ljava/lang/Integer;"));
84 return result;
85 }
86
GetIntegerValueOfArrayDataOffset(ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects)87 MemberOffset IntrinsicObjects::GetIntegerValueOfArrayDataOffset(
88 ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects) {
89 DCHECK(HasIntrinsicObjects(boot_image_live_objects));
90 MemberOffset result =
91 mirror::ObjectArray<mirror::Object>::OffsetOfElement(kIntrinsicObjectsOffset + 1u);
92 DCHECK_EQ(GetIntegerValueOfObject(boot_image_live_objects, 0u),
93 (boot_image_live_objects
94 ->GetFieldObject<mirror::Object, kVerifyNone, kWithoutReadBarrier>(result)));
95 return result;
96 }
97
98 } // namespace art
99