blob: 619cd8ed414f90fef68167ff760a947e9fd9a000 [file] [log] [blame]
Andreas Gampe71fb52f2014-12-29 17:43:08 -08001/*
2 * Copyright (C) 2015 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 "intrinsics.h"
18
Andreas Gampea1d2f952017-04-20 22:53:58 -070019#include "art_field-inl.h"
Andreas Gampec6ea7d02017-02-01 16:46:28 -080020#include "art_method-inl.h"
David Sehrc431b9d2018-03-02 12:01:51 -080021#include "base/utils.h"
Andreas Gampebfb5ba92015-09-01 15:45:02 +000022#include "class_linker.h"
David Sehr8c0961f2018-01-23 16:11:38 -080023#include "dex/invoke_type.h"
Nicolas Geoffray331605a2017-03-01 11:01:41 +000024#include "driver/compiler_options.h"
Vladimir Markoeebb8212018-06-05 14:57:24 +010025#include "gc/space/image_space.h"
26#include "image-inl.h"
27#include "intrinsic_objects.h"
Andreas Gampe71fb52f2014-12-29 17:43:08 -080028#include "nodes.h"
Vladimir Markoeebb8212018-06-05 14:57:24 +010029#include "obj_ptr-inl.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070030#include "scoped_thread_state_change-inl.h"
Andreas Gampeb486a982017-06-01 13:45:54 -070031#include "thread-current-inl.h"
Andreas Gampe71fb52f2014-12-29 17:43:08 -080032
33namespace art {
34
Andreas Gampe71fb52f2014-12-29 17:43:08 -080035std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic) {
36 switch (intrinsic) {
37 case Intrinsics::kNone:
David Brazdil109c89a2015-07-31 17:10:43 +010038 os << "None";
Andreas Gampe71fb52f2014-12-29 17:43:08 -080039 break;
Nicolas Geoffray762869d2016-07-15 15:28:35 +010040#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
Andreas Gampe71fb52f2014-12-29 17:43:08 -080041 case Intrinsics::k ## Name: \
42 os << # Name; \
43 break;
44#include "intrinsics_list.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070045 INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
Andreas Gampe71fb52f2014-12-29 17:43:08 -080046#undef STATIC_INTRINSICS_LIST
47#undef VIRTUAL_INTRINSICS_LIST
48#undef OPTIMIZING_INTRINSICS
49 }
50 return os;
51}
52
Vladimir Marko6fd16062018-06-26 11:02:04 +010053static const char kIntegerCacheDescriptor[] = "Ljava/lang/Integer$IntegerCache;";
54static const char kIntegerDescriptor[] = "Ljava/lang/Integer;";
55static const char kIntegerArrayDescriptor[] = "[Ljava/lang/Integer;";
56static const char kLowFieldName[] = "low";
57static const char kHighFieldName[] = "high";
58static const char kValueFieldName[] = "value";
59
Vladimir Markoeebb8212018-06-05 14:57:24 +010060static ObjPtr<mirror::ObjectArray<mirror::Object>> GetBootImageLiveObjects()
61 REQUIRES_SHARED(Locks::mutator_lock_) {
62 gc::Heap* heap = Runtime::Current()->GetHeap();
63 const std::vector<gc::space::ImageSpace*>& boot_image_spaces = heap->GetBootImageSpaces();
64 DCHECK(!boot_image_spaces.empty());
65 const ImageHeader& main_header = boot_image_spaces[0]->GetImageHeader();
66 ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects =
67 ObjPtr<mirror::ObjectArray<mirror::Object>>::DownCast(
68 main_header.GetImageRoot<kWithoutReadBarrier>(ImageHeader::kBootImageLiveObjects));
69 DCHECK(boot_image_live_objects != nullptr);
70 DCHECK(heap->ObjectIsInBootImageSpace(boot_image_live_objects));
71 return boot_image_live_objects;
72}
73
Vladimir Marko6fd16062018-06-26 11:02:04 +010074static ObjPtr<mirror::Class> LookupInitializedClass(Thread* self,
75 ClassLinker* class_linker,
76 const char* descriptor)
77 REQUIRES_SHARED(Locks::mutator_lock_) {
78 ObjPtr<mirror::Class> klass =
79 class_linker->LookupClass(self, descriptor, /* class_loader */ nullptr);
80 DCHECK(klass != nullptr);
81 DCHECK(klass->IsInitialized());
82 return klass;
83}
84
85static ObjPtr<mirror::ObjectArray<mirror::Object>> GetIntegerCacheArray(
86 ObjPtr<mirror::Class> cache_class) REQUIRES_SHARED(Locks::mutator_lock_) {
87 ArtField* cache_field = cache_class->FindDeclaredStaticField("cache", kIntegerArrayDescriptor);
88 DCHECK(cache_field != nullptr);
89 return ObjPtr<mirror::ObjectArray<mirror::Object>>::DownCast(cache_field->GetObject(cache_class));
90}
91
92static int32_t GetIntegerCacheField(ObjPtr<mirror::Class> cache_class, const char* field_name)
93 REQUIRES_SHARED(Locks::mutator_lock_) {
94 ArtField* field = cache_class->FindDeclaredStaticField(field_name, "I");
95 DCHECK(field != nullptr);
96 return field->GetInt(cache_class);
97}
98
Vladimir Markoeebb8212018-06-05 14:57:24 +010099static bool CheckIntegerCache(Thread* self,
100 ClassLinker* class_linker,
101 ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects,
102 ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_cache)
103 REQUIRES_SHARED(Locks::mutator_lock_) {
104 DCHECK(boot_image_cache != nullptr);
105
106 // Since we have a cache in the boot image, both java.lang.Integer and
107 // java.lang.Integer$IntegerCache must be initialized in the boot image.
Vladimir Marko6fd16062018-06-26 11:02:04 +0100108 ObjPtr<mirror::Class> cache_class =
109 LookupInitializedClass(self, class_linker, kIntegerCacheDescriptor);
Vladimir Markoeebb8212018-06-05 14:57:24 +0100110 ObjPtr<mirror::Class> integer_class =
Vladimir Marko6fd16062018-06-26 11:02:04 +0100111 LookupInitializedClass(self, class_linker, kIntegerDescriptor);
Vladimir Markoeebb8212018-06-05 14:57:24 +0100112
113 // Check that the current cache is the same as the `boot_image_cache`.
Vladimir Marko6fd16062018-06-26 11:02:04 +0100114 ObjPtr<mirror::ObjectArray<mirror::Object>> current_cache = GetIntegerCacheArray(cache_class);
Vladimir Markoeebb8212018-06-05 14:57:24 +0100115 if (current_cache != boot_image_cache) {
116 return false; // Messed up IntegerCache.cache.
117 }
118
119 // Check that the range matches the boot image cache length.
Vladimir Marko6fd16062018-06-26 11:02:04 +0100120 int32_t low = GetIntegerCacheField(cache_class, kLowFieldName);
121 int32_t high = GetIntegerCacheField(cache_class, kHighFieldName);
Vladimir Markoeebb8212018-06-05 14:57:24 +0100122 if (boot_image_cache->GetLength() != high - low + 1) {
123 return false; // Messed up IntegerCache.low or IntegerCache.high.
124 }
125
126 // Check that the elements match the boot image intrinsic objects and check their values as well.
Vladimir Marko6fd16062018-06-26 11:02:04 +0100127 ArtField* value_field = integer_class->FindDeclaredInstanceField(kValueFieldName, "I");
Vladimir Markoeebb8212018-06-05 14:57:24 +0100128 DCHECK(value_field != nullptr);
129 for (int32_t i = 0, len = boot_image_cache->GetLength(); i != len; ++i) {
130 ObjPtr<mirror::Object> boot_image_object =
131 IntrinsicObjects::GetIntegerValueOfObject(boot_image_live_objects, i);
132 DCHECK(Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(boot_image_object));
133 // No need for read barrier for comparison with a boot image object.
134 ObjPtr<mirror::Object> current_object =
135 boot_image_cache->GetWithoutChecks<kVerifyNone, kWithoutReadBarrier>(i);
136 if (boot_image_object != current_object) {
137 return false; // Messed up IntegerCache.cache[i]
138 }
139 if (value_field->GetInt(boot_image_object) != low + i) {
140 return false; // Messed up IntegerCache.cache[i].value.
141 }
142 }
143
144 return true;
145}
146
Nicolas Geoffray331605a2017-03-01 11:01:41 +0000147void IntrinsicVisitor::ComputeIntegerValueOfLocations(HInvoke* invoke,
148 CodeGenerator* codegen,
149 Location return_location,
150 Location first_argument_location) {
Nicolas Geoffray331605a2017-03-01 11:01:41 +0000151 // The intrinsic will call if it needs to allocate a j.l.Integer.
Vladimir Markoeebb8212018-06-05 14:57:24 +0100152 LocationSummary::CallKind call_kind = LocationSummary::kCallOnMainOnly;
Vladimir Marko6fd16062018-06-26 11:02:04 +0100153 const CompilerOptions& compiler_options = codegen->GetCompilerOptions();
154 if (compiler_options.IsBootImage()) {
155 // Piggyback on the method load kind to determine whether we can use PC-relative addressing.
156 // This should cover both the testing config (non-PIC boot image) and codegens that reject
157 // PC-relative load kinds and fall back to the runtime call.
158 if (!invoke->AsInvokeStaticOrDirect()->HasPcRelativeMethodLoadKind()) {
159 return;
160 }
161 if (!compiler_options.IsImageClass(kIntegerCacheDescriptor) ||
162 !compiler_options.IsImageClass(kIntegerDescriptor)) {
163 return;
164 }
165 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
166 Thread* self = Thread::Current();
167 ScopedObjectAccess soa(self);
168 ObjPtr<mirror::Class> cache_class = class_linker->LookupClass(
169 self, kIntegerCacheDescriptor, /* class_loader */ nullptr);
170 DCHECK(cache_class != nullptr);
171 if (UNLIKELY(!cache_class->IsInitialized())) {
172 LOG(WARNING) << "Image class " << cache_class->PrettyDescriptor() << " is uninitialized.";
173 return;
174 }
175 ObjPtr<mirror::Class> integer_class =
176 class_linker->LookupClass(self, kIntegerDescriptor, /* class_loader */ nullptr);
177 DCHECK(integer_class != nullptr);
178 if (UNLIKELY(!integer_class->IsInitialized())) {
179 LOG(WARNING) << "Image class " << integer_class->PrettyDescriptor() << " is uninitialized.";
180 return;
181 }
182 int32_t low = GetIntegerCacheField(cache_class, kLowFieldName);
183 int32_t high = GetIntegerCacheField(cache_class, kHighFieldName);
184 if (kIsDebugBuild) {
185 ObjPtr<mirror::ObjectArray<mirror::Object>> current_cache = GetIntegerCacheArray(cache_class);
186 CHECK(current_cache != nullptr);
187 CHECK_EQ(current_cache->GetLength(), high - low + 1);
188 ArtField* value_field = integer_class->FindDeclaredInstanceField(kValueFieldName, "I");
189 CHECK(value_field != nullptr);
190 for (int32_t i = 0, len = current_cache->GetLength(); i != len; ++i) {
191 ObjPtr<mirror::Object> current_object = current_cache->GetWithoutChecks(i);
192 CHECK(current_object != nullptr);
193 CHECK_EQ(value_field->GetInt(current_object), low + i);
194 }
195 }
196 if (invoke->InputAt(0)->IsIntConstant()) {
197 int32_t value = invoke->InputAt(0)->AsIntConstant()->GetValue();
198 if (static_cast<uint32_t>(value) - static_cast<uint32_t>(low) <
199 static_cast<uint32_t>(high - low + 1)) {
200 // No call, we shall use direct pointer to the Integer object.
201 call_kind = LocationSummary::kNoCall;
202 }
203 }
204 } else {
205 Runtime* runtime = Runtime::Current();
206 if (runtime->GetHeap()->GetBootImageSpaces().empty()) {
207 return; // Running without boot image, cannot use required boot image objects.
208 }
Vladimir Markoeebb8212018-06-05 14:57:24 +0100209 Thread* self = Thread::Current();
210 ScopedObjectAccess soa(self);
211 ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects = GetBootImageLiveObjects();
212 ObjPtr<mirror::ObjectArray<mirror::Object>> cache =
213 IntrinsicObjects::GetIntegerValueOfCache(boot_image_live_objects);
214 if (cache == nullptr) {
215 return; // No cache in the boot image.
216 }
217 if (runtime->UseJitCompilation()) {
218 if (!CheckIntegerCache(self, runtime->GetClassLinker(), boot_image_live_objects, cache)) {
219 return; // The cache was somehow messed up, probably by using reflection.
220 }
221 } else {
222 DCHECK(runtime->IsAotCompiler());
223 DCHECK(CheckIntegerCache(self, runtime->GetClassLinker(), boot_image_live_objects, cache));
224 if (invoke->InputAt(0)->IsIntConstant()) {
225 int32_t value = invoke->InputAt(0)->AsIntConstant()->GetValue();
226 // Retrieve the `value` from the lowest cached Integer.
227 ObjPtr<mirror::Object> low_integer =
228 IntrinsicObjects::GetIntegerValueOfObject(boot_image_live_objects, 0u);
229 ObjPtr<mirror::Class> integer_class =
230 low_integer->GetClass<kVerifyNone, kWithoutReadBarrier>();
Vladimir Marko6fd16062018-06-26 11:02:04 +0100231 ArtField* value_field = integer_class->FindDeclaredInstanceField(kValueFieldName, "I");
Vladimir Markoeebb8212018-06-05 14:57:24 +0100232 DCHECK(value_field != nullptr);
233 int32_t low = value_field->GetInt(low_integer);
234 if (static_cast<uint32_t>(value) - static_cast<uint32_t>(low) <
235 static_cast<uint32_t>(cache->GetLength())) {
236 // No call, we shall use direct pointer to the Integer object. Note that we cannot
237 // do this for JIT as the "low" can change through reflection before emitting the code.
238 call_kind = LocationSummary::kNoCall;
239 }
240 }
241 }
Nicolas Geoffray331605a2017-03-01 11:01:41 +0000242 }
Vladimir Markoeebb8212018-06-05 14:57:24 +0100243
244 ArenaAllocator* allocator = invoke->GetBlock()->GetGraph()->GetAllocator();
245 LocationSummary* locations = new (allocator) LocationSummary(invoke, call_kind, kIntrinsified);
246 if (call_kind == LocationSummary::kCallOnMainOnly) {
247 locations->SetInAt(0, Location::RegisterOrConstant(invoke->InputAt(0)));
248 locations->AddTemp(first_argument_location);
249 locations->SetOut(return_location);
250 } else {
251 locations->SetInAt(0, Location::ConstantLocation(invoke->InputAt(0)->AsConstant()));
252 locations->SetOut(Location::RequiresRegister());
253 }
Nicolas Geoffray331605a2017-03-01 11:01:41 +0000254}
255
Vladimir Marko6fd16062018-06-26 11:02:04 +0100256static int32_t GetIntegerCacheLowFromIntegerCache(Thread* self, ClassLinker* class_linker)
Vladimir Markoeebb8212018-06-05 14:57:24 +0100257 REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko6fd16062018-06-26 11:02:04 +0100258 ObjPtr<mirror::Class> cache_class =
259 LookupInitializedClass(self, class_linker, kIntegerCacheDescriptor);
260 return GetIntegerCacheField(cache_class, kLowFieldName);
Vladimir Markoeebb8212018-06-05 14:57:24 +0100261}
262
263static uint32_t CalculateBootImageOffset(ObjPtr<mirror::Object> object)
264 REQUIRES_SHARED(Locks::mutator_lock_) {
265 gc::Heap* heap = Runtime::Current()->GetHeap();
266 DCHECK(heap->ObjectIsInBootImageSpace(object));
267 return reinterpret_cast<const uint8_t*>(object.Ptr()) - heap->GetBootImageSpaces()[0]->Begin();
268}
269
270inline IntrinsicVisitor::IntegerValueOfInfo::IntegerValueOfInfo()
Vladimir Marko6fd16062018-06-26 11:02:04 +0100271 : value_offset(0),
Vladimir Markoeebb8212018-06-05 14:57:24 +0100272 low(0),
273 length(0u),
Vladimir Marko6fd16062018-06-26 11:02:04 +0100274 integer_boot_image_offset(kInvalidReference),
275 value_boot_image_reference(kInvalidReference) {}
Vladimir Markoeebb8212018-06-05 14:57:24 +0100276
Vladimir Marko6fd16062018-06-26 11:02:04 +0100277IntrinsicVisitor::IntegerValueOfInfo IntrinsicVisitor::ComputeIntegerValueOfInfo(
278 HInvoke* invoke, const CompilerOptions& compiler_options) {
Nicolas Geoffray331605a2017-03-01 11:01:41 +0000279 // Note that we could cache all of the data looked up here. but there's no good
280 // location for it. We don't want to add it to WellKnownClasses, to avoid creating global
281 // jni values. Adding it as state to the compiler singleton seems like wrong
282 // separation of concerns.
283 // The need for this data should be pretty rare though.
284
Vladimir Markoeebb8212018-06-05 14:57:24 +0100285 // Note that at this point we can no longer abort the code generation. Therefore,
286 // we need to provide data that shall not lead to a crash even if the fields were
287 // modified through reflection since ComputeIntegerValueOfLocations() when JITting.
288
289 Runtime* runtime = Runtime::Current();
Vladimir Marko6fd16062018-06-26 11:02:04 +0100290 ClassLinker* class_linker = runtime->GetClassLinker();
Nicolas Geoffray331605a2017-03-01 11:01:41 +0000291 Thread* self = Thread::Current();
292 ScopedObjectAccess soa(self);
Vladimir Markoeebb8212018-06-05 14:57:24 +0100293
Nicolas Geoffray331605a2017-03-01 11:01:41 +0000294 IntegerValueOfInfo info;
Vladimir Marko6fd16062018-06-26 11:02:04 +0100295 if (compiler_options.IsBootImage()) {
296 ObjPtr<mirror::Class> integer_class =
297 LookupInitializedClass(self, class_linker, kIntegerDescriptor);
298 ArtField* value_field = integer_class->FindDeclaredInstanceField(kValueFieldName, "I");
299 DCHECK(value_field != nullptr);
300 info.value_offset = value_field->GetOffset().Uint32Value();
301 ObjPtr<mirror::Class> cache_class =
302 LookupInitializedClass(self, class_linker, kIntegerCacheDescriptor);
303 info.low = GetIntegerCacheField(cache_class, kLowFieldName);
304 int32_t high = GetIntegerCacheField(cache_class, kHighFieldName);
305 info.length = dchecked_integral_cast<uint32_t>(high - info.low + 1);
Vladimir Markoeebb8212018-06-05 14:57:24 +0100306
Vladimir Marko6fd16062018-06-26 11:02:04 +0100307 info.integer_boot_image_offset = IntegerValueOfInfo::kInvalidReference;
308 if (invoke->InputAt(0)->IsIntConstant()) {
309 int32_t input_value = invoke->InputAt(0)->AsIntConstant()->GetValue();
310 uint32_t index = static_cast<uint32_t>(input_value) - static_cast<uint32_t>(info.low);
311 if (index < static_cast<uint32_t>(info.length)) {
312 info.value_boot_image_reference = IntrinsicObjects::EncodePatch(
313 IntrinsicObjects::PatchType::kIntegerValueOfObject, index);
314 } else {
315 // Not in the cache.
316 info.value_boot_image_reference = IntegerValueOfInfo::kInvalidReference;
317 }
Vladimir Markoeebb8212018-06-05 14:57:24 +0100318 } else {
Vladimir Marko6fd16062018-06-26 11:02:04 +0100319 info.array_data_boot_image_reference =
320 IntrinsicObjects::EncodePatch(IntrinsicObjects::PatchType::kIntegerValueOfArray);
Vladimir Markoeebb8212018-06-05 14:57:24 +0100321 }
322 } else {
Vladimir Marko6fd16062018-06-26 11:02:04 +0100323 ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects = GetBootImageLiveObjects();
324 ObjPtr<mirror::Object> low_integer =
325 IntrinsicObjects::GetIntegerValueOfObject(boot_image_live_objects, 0u);
326 ObjPtr<mirror::Class> integer_class = low_integer->GetClass<kVerifyNone, kWithoutReadBarrier>();
327 ArtField* value_field = integer_class->FindDeclaredInstanceField(kValueFieldName, "I");
328 DCHECK(value_field != nullptr);
329 info.value_offset = value_field->GetOffset().Uint32Value();
330 if (runtime->UseJitCompilation()) {
331 // Use the current `IntegerCache.low` for JIT to avoid truly surprising behavior if the
332 // code messes up the `value` field in the lowest cached Integer using reflection.
333 info.low = GetIntegerCacheLowFromIntegerCache(self, class_linker);
334 } else {
335 // For app AOT, the `low_integer->value` should be the same as `IntegerCache.low`.
336 info.low = value_field->GetInt(low_integer);
337 DCHECK_EQ(info.low, GetIntegerCacheLowFromIntegerCache(self, class_linker));
338 }
339 // Do not look at `IntegerCache.high`, use the immutable length of the cache array instead.
340 info.length = dchecked_integral_cast<uint32_t>(
341 IntrinsicObjects::GetIntegerValueOfCache(boot_image_live_objects)->GetLength());
342
343 info.integer_boot_image_offset = CalculateBootImageOffset(integer_class);
344 if (invoke->InputAt(0)->IsIntConstant()) {
345 int32_t input_value = invoke->InputAt(0)->AsIntConstant()->GetValue();
346 uint32_t index = static_cast<uint32_t>(input_value) - static_cast<uint32_t>(info.low);
347 if (index < static_cast<uint32_t>(info.length)) {
348 ObjPtr<mirror::Object> integer =
349 IntrinsicObjects::GetIntegerValueOfObject(boot_image_live_objects, index);
350 info.value_boot_image_reference = CalculateBootImageOffset(integer);
351 } else {
352 // Not in the cache.
353 info.value_boot_image_reference = IntegerValueOfInfo::kInvalidReference;
354 }
355 } else {
356 info.array_data_boot_image_reference =
357 CalculateBootImageOffset(boot_image_live_objects) +
358 IntrinsicObjects::GetIntegerValueOfArrayDataOffset(boot_image_live_objects).Uint32Value();
359 }
Nicolas Geoffray331605a2017-03-01 11:01:41 +0000360 }
361
Nicolas Geoffray331605a2017-03-01 11:01:41 +0000362 return info;
363}
364
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800365} // namespace art