blob: 3c20ad698b526db34545bb3d87a9a638acc251d4 [file] [log] [blame]
Vladimir Markoeebb8212018-06-05 14:57:24 +01001/*
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/logging.h"
21#include "class_root.h"
22#include "handle.h"
23#include "obj_ptr-inl.h"
24#include "mirror/object_array-inl.h"
25
26namespace art {
27
28static ObjPtr<mirror::ObjectArray<mirror::Object>> LookupIntegerCache(Thread* self,
29 ClassLinker* class_linker)
30 REQUIRES_SHARED(Locks::mutator_lock_) {
31 ObjPtr<mirror::Class> integer_cache_class = class_linker->LookupClass(
32 self, "Ljava/lang/Integer$IntegerCache;", /* class_linker */ nullptr);
33 if (integer_cache_class == nullptr || !integer_cache_class->IsInitialized()) {
34 return nullptr;
35 }
36 ArtField* cache_field =
37 integer_cache_class->FindDeclaredStaticField("cache", "[Ljava/lang/Integer;");
38 CHECK(cache_field != nullptr);
39 ObjPtr<mirror::ObjectArray<mirror::Object>> integer_cache =
40 ObjPtr<mirror::ObjectArray<mirror::Object>>::DownCast(
41 cache_field->GetObject(integer_cache_class));
42 CHECK(integer_cache != nullptr);
43 return integer_cache;
44}
45
46ObjPtr<mirror::ObjectArray<mirror::Object>> IntrinsicObjects::AllocateBootImageLiveObjects(
47 Thread* self,
48 ClassLinker* class_linker) REQUIRES_SHARED(Locks::mutator_lock_) {
49 // The objects used for the Integer.valueOf() intrinsic must remain live even if references
50 // to them are removed using reflection. Image roots are not accessible through reflection,
51 // so the array we construct here shall keep them alive.
52 StackHandleScope<1> hs(self);
53 Handle<mirror::ObjectArray<mirror::Object>> integer_cache =
54 hs.NewHandle(LookupIntegerCache(self, class_linker));
55 size_t live_objects_size =
56 (integer_cache != nullptr) ? (/* cache */ 1u + integer_cache->GetLength()) : 0u;
57 ObjPtr<mirror::ObjectArray<mirror::Object>> live_objects =
58 mirror::ObjectArray<mirror::Object>::Alloc(
59 self, GetClassRoot<mirror::ObjectArray<mirror::Object>>(class_linker), live_objects_size);
60 int32_t index = 0;
61 if (integer_cache != nullptr) {
62 live_objects->Set(index++, integer_cache.Get());
63 for (int32_t i = 0, length = integer_cache->GetLength(); i != length; ++i) {
64 live_objects->Set(index++, integer_cache->Get(i));
65 }
66 }
67 CHECK_EQ(index, live_objects->GetLength());
68
69 if (kIsDebugBuild && integer_cache != nullptr) {
70 CHECK_EQ(integer_cache.Get(), GetIntegerValueOfCache(live_objects));
71 for (int32_t i = 0, len = integer_cache->GetLength(); i != len; ++i) {
72 CHECK_EQ(integer_cache->GetWithoutChecks(i), GetIntegerValueOfObject(live_objects, i));
73 }
74 }
75 return live_objects;
76}
77
78ObjPtr<mirror::ObjectArray<mirror::Object>> IntrinsicObjects::GetIntegerValueOfCache(
79 ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects) {
80 DCHECK(boot_image_live_objects != nullptr);
81 if (boot_image_live_objects->GetLength() == 0u) {
82 return nullptr; // No intrinsic objects.
83 }
84 // No need for read barrier for boot image object or for verifying the value that was just stored.
85 ObjPtr<mirror::Object> result =
86 boot_image_live_objects->GetWithoutChecks<kVerifyNone, kWithoutReadBarrier>(0);
87 DCHECK(result != nullptr);
88 DCHECK(result->IsObjectArray());
89 DCHECK(result->GetClass()->DescriptorEquals("[Ljava/lang/Integer;"));
90 return ObjPtr<mirror::ObjectArray<mirror::Object>>::DownCast(result);
91}
92
93ObjPtr<mirror::Object> IntrinsicObjects::GetIntegerValueOfObject(
94 ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects,
95 uint32_t index) {
96 DCHECK(boot_image_live_objects != nullptr);
97 DCHECK_NE(boot_image_live_objects->GetLength(), 0);
98 DCHECK_LT(index,
99 static_cast<uint32_t>(GetIntegerValueOfCache(boot_image_live_objects)->GetLength()));
100
101 // No need for read barrier for boot image object or for verifying the value that was just stored.
102 ObjPtr<mirror::Object> result =
103 boot_image_live_objects->GetWithoutChecks<kVerifyNone, kWithoutReadBarrier>(
104 /* skip the IntegerCache.cache */ 1u + index);
105 DCHECK(result != nullptr);
106 DCHECK(result->GetClass()->DescriptorEquals("Ljava/lang/Integer;"));
107 return result;
108}
109
110MemberOffset IntrinsicObjects::GetIntegerValueOfArrayDataOffset(
111 ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects) {
112 DCHECK_NE(boot_image_live_objects->GetLength(), 0);
113 MemberOffset result = mirror::ObjectArray<mirror::Object>::OffsetOfElement(1u);
114 DCHECK_EQ(GetIntegerValueOfObject(boot_image_live_objects, 0u),
115 (boot_image_live_objects
116 ->GetFieldObject<mirror::Object, kVerifyNone, kWithoutReadBarrier>(result)));
117 return result;
118}
119
120} // namespace art