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