blob: a2a190e5884e8dc317f0276a8c6850b39851be7e [file] [log] [blame]
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001/*
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 "unstarted_runtime.h"
18
Andreas Gampe8ce9c302016-04-15 21:24:28 -070019#include <ctype.h>
Andreas Gampe13fc1be2016-04-05 20:14:30 -070020#include <errno.h>
21#include <stdlib.h>
22
Andreas Gampe2969bcd2015-03-09 12:57:41 -070023#include <cmath>
Andreas Gampe13fc1be2016-04-05 20:14:30 -070024#include <limits>
Andreas Gampe8ce9c302016-04-15 21:24:28 -070025#include <locale>
Andreas Gampe2969bcd2015-03-09 12:57:41 -070026#include <unordered_map>
27
Andreas Gampeaacc25d2015-04-01 14:49:06 -070028#include "ScopedLocalRef.h"
29
Mathieu Chartiere401d142015-04-22 13:56:20 -070030#include "art_method-inl.h"
Andreas Gampebc4d2182016-02-22 10:03:12 -080031#include "base/casts.h"
Andreas Gampe2969bcd2015-03-09 12:57:41 -070032#include "base/logging.h"
33#include "base/macros.h"
34#include "class_linker.h"
35#include "common_throws.h"
36#include "entrypoints/entrypoint_utils-inl.h"
Andreas Gampebc4d2182016-02-22 10:03:12 -080037#include "gc/reference_processor.h"
Andreas Gampe2969bcd2015-03-09 12:57:41 -070038#include "handle_scope-inl.h"
39#include "interpreter/interpreter_common.h"
40#include "mirror/array-inl.h"
Andreas Gampe2969bcd2015-03-09 12:57:41 -070041#include "mirror/class.h"
Mathieu Chartierdaaf3262015-03-24 13:30:28 -070042#include "mirror/field-inl.h"
Andreas Gampe2969bcd2015-03-09 12:57:41 -070043#include "mirror/object-inl.h"
44#include "mirror/object_array-inl.h"
45#include "mirror/string-inl.h"
46#include "nth_caller_visitor.h"
47#include "thread.h"
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020048#include "transaction.h"
Andreas Gampe2969bcd2015-03-09 12:57:41 -070049#include "well_known_classes.h"
Andreas Gampef778eb22015-04-13 14:17:09 -070050#include "zip_archive.h"
Andreas Gampe2969bcd2015-03-09 12:57:41 -070051
52namespace art {
53namespace interpreter {
54
Andreas Gampe068b0c02015-03-11 12:44:47 -070055static void AbortTransactionOrFail(Thread* self, const char* fmt, ...)
Sebastien Hertz45b15972015-04-03 16:07:05 +020056 __attribute__((__format__(__printf__, 2, 3)))
Mathieu Chartier90443472015-07-16 20:32:27 -070057 SHARED_REQUIRES(Locks::mutator_lock_);
Sebastien Hertz45b15972015-04-03 16:07:05 +020058
59static void AbortTransactionOrFail(Thread* self, const char* fmt, ...) {
Andreas Gampe068b0c02015-03-11 12:44:47 -070060 va_list args;
Andreas Gampe068b0c02015-03-11 12:44:47 -070061 if (Runtime::Current()->IsActiveTransaction()) {
Sebastien Hertz45b15972015-04-03 16:07:05 +020062 va_start(args, fmt);
63 AbortTransactionV(self, fmt, args);
Andreas Gampe068b0c02015-03-11 12:44:47 -070064 va_end(args);
65 } else {
Sebastien Hertz45b15972015-04-03 16:07:05 +020066 va_start(args, fmt);
67 std::string msg;
68 StringAppendV(&msg, fmt, args);
69 va_end(args);
70 LOG(FATAL) << "Trying to abort, but not in transaction mode: " << msg;
Andreas Gampe068b0c02015-03-11 12:44:47 -070071 UNREACHABLE();
72 }
73}
74
Andreas Gampe8ce9c302016-04-15 21:24:28 -070075// Restricted support for character upper case / lower case. Only support ASCII, where
76// it's easy. Abort the transaction otherwise.
77static void CharacterLowerUpper(Thread* self,
78 ShadowFrame* shadow_frame,
79 JValue* result,
80 size_t arg_offset,
81 bool to_lower_case) SHARED_REQUIRES(Locks::mutator_lock_) {
82 uint32_t int_value = static_cast<uint32_t>(shadow_frame->GetVReg(arg_offset));
83
84 // Only ASCII (7-bit).
85 if (!isascii(int_value)) {
86 AbortTransactionOrFail(self,
87 "Only support ASCII characters for toLowerCase/toUpperCase: %u",
88 int_value);
89 return;
90 }
91
92 std::locale c_locale("C");
93 char char_value = static_cast<char>(int_value);
94
95 if (to_lower_case) {
96 result->SetI(std::tolower(char_value, c_locale));
97 } else {
98 result->SetI(std::toupper(char_value, c_locale));
99 }
100}
101
102void UnstartedRuntime::UnstartedCharacterToLowerCase(
103 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
104 CharacterLowerUpper(self, shadow_frame, result, arg_offset, true);
105}
106
107void UnstartedRuntime::UnstartedCharacterToUpperCase(
108 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
109 CharacterLowerUpper(self, shadow_frame, result, arg_offset, false);
110}
111
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700112// Helper function to deal with class loading in an unstarted runtime.
113static void UnstartedRuntimeFindClass(Thread* self, Handle<mirror::String> className,
114 Handle<mirror::ClassLoader> class_loader, JValue* result,
115 const std::string& method_name, bool initialize_class,
116 bool abort_if_not_found)
Mathieu Chartier90443472015-07-16 20:32:27 -0700117 SHARED_REQUIRES(Locks::mutator_lock_) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700118 CHECK(className.Get() != nullptr);
119 std::string descriptor(DotToDescriptor(className->ToModifiedUtf8().c_str()));
120 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
121
122 mirror::Class* found = class_linker->FindClass(self, descriptor.c_str(), class_loader);
123 if (found == nullptr && abort_if_not_found) {
124 if (!self->IsExceptionPending()) {
Andreas Gampe068b0c02015-03-11 12:44:47 -0700125 AbortTransactionOrFail(self, "%s failed in un-started runtime for class: %s",
126 method_name.c_str(), PrettyDescriptor(descriptor.c_str()).c_str());
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700127 }
128 return;
129 }
130 if (found != nullptr && initialize_class) {
131 StackHandleScope<1> hs(self);
132 Handle<mirror::Class> h_class(hs.NewHandle(found));
133 if (!class_linker->EnsureInitialized(self, h_class, true, true)) {
134 CHECK(self->IsExceptionPending());
135 return;
136 }
137 }
138 result->SetL(found);
139}
140
141// Common helper for class-loading cutouts in an unstarted runtime. We call Runtime methods that
142// rely on Java code to wrap errors in the correct exception class (i.e., NoClassDefFoundError into
143// ClassNotFoundException), so need to do the same. The only exception is if the exception is
Sebastien Hertz2fd7e692015-04-02 11:11:19 +0200144// actually the transaction abort exception. This must not be wrapped, as it signals an
145// initialization abort.
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700146static void CheckExceptionGenerateClassNotFound(Thread* self)
Mathieu Chartier90443472015-07-16 20:32:27 -0700147 SHARED_REQUIRES(Locks::mutator_lock_) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700148 if (self->IsExceptionPending()) {
Sebastien Hertz2fd7e692015-04-02 11:11:19 +0200149 // If it is not the transaction abort exception, wrap it.
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700150 std::string type(PrettyTypeOf(self->GetException()));
Sebastien Hertz2fd7e692015-04-02 11:11:19 +0200151 if (type != Transaction::kAbortExceptionDescriptor) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700152 self->ThrowNewWrappedException("Ljava/lang/ClassNotFoundException;",
153 "ClassNotFoundException");
154 }
155 }
156}
157
Andreas Gampe5d4bb1d2015-04-14 22:16:14 -0700158static mirror::String* GetClassName(Thread* self, ShadowFrame* shadow_frame, size_t arg_offset)
Mathieu Chartier90443472015-07-16 20:32:27 -0700159 SHARED_REQUIRES(Locks::mutator_lock_) {
Andreas Gampe5d4bb1d2015-04-14 22:16:14 -0700160 mirror::Object* param = shadow_frame->GetVRegReference(arg_offset);
161 if (param == nullptr) {
162 AbortTransactionOrFail(self, "Null-pointer in Class.forName.");
163 return nullptr;
164 }
165 return param->AsString();
166}
167
Andreas Gampe799681b2015-05-15 19:24:12 -0700168void UnstartedRuntime::UnstartedClassForName(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700169 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe5d4bb1d2015-04-14 22:16:14 -0700170 mirror::String* class_name = GetClassName(self, shadow_frame, arg_offset);
171 if (class_name == nullptr) {
172 return;
173 }
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700174 StackHandleScope<1> hs(self);
175 Handle<mirror::String> h_class_name(hs.NewHandle(class_name));
Mathieu Chartier9865bde2015-12-21 09:58:16 -0800176 UnstartedRuntimeFindClass(self,
177 h_class_name,
178 ScopedNullHandle<mirror::ClassLoader>(),
179 result,
180 "Class.forName",
181 true,
182 false);
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700183 CheckExceptionGenerateClassNotFound(self);
184}
185
Andreas Gampe799681b2015-05-15 19:24:12 -0700186void UnstartedRuntime::UnstartedClassForNameLong(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700187 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe5d4bb1d2015-04-14 22:16:14 -0700188 mirror::String* class_name = GetClassName(self, shadow_frame, arg_offset);
189 if (class_name == nullptr) {
Andreas Gampebf4d3af2015-04-14 10:10:33 -0700190 return;
191 }
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700192 bool initialize_class = shadow_frame->GetVReg(arg_offset + 1) != 0;
193 mirror::ClassLoader* class_loader =
194 down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset + 2));
195 StackHandleScope<2> hs(self);
196 Handle<mirror::String> h_class_name(hs.NewHandle(class_name));
197 Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(class_loader));
198 UnstartedRuntimeFindClass(self, h_class_name, h_class_loader, result, "Class.forName",
199 initialize_class, false);
200 CheckExceptionGenerateClassNotFound(self);
201}
202
Andreas Gampe799681b2015-05-15 19:24:12 -0700203void UnstartedRuntime::UnstartedClassClassForName(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700204 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe5d4bb1d2015-04-14 22:16:14 -0700205 mirror::String* class_name = GetClassName(self, shadow_frame, arg_offset);
206 if (class_name == nullptr) {
207 return;
208 }
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700209 bool initialize_class = shadow_frame->GetVReg(arg_offset + 1) != 0;
210 mirror::ClassLoader* class_loader =
211 down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset + 2));
212 StackHandleScope<2> hs(self);
213 Handle<mirror::String> h_class_name(hs.NewHandle(class_name));
214 Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(class_loader));
215 UnstartedRuntimeFindClass(self, h_class_name, h_class_loader, result, "Class.classForName",
216 initialize_class, false);
217 CheckExceptionGenerateClassNotFound(self);
218}
219
Andreas Gampe799681b2015-05-15 19:24:12 -0700220void UnstartedRuntime::UnstartedClassNewInstance(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700221 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
222 StackHandleScope<2> hs(self); // Class, constructor, object.
Andreas Gampe5d4bb1d2015-04-14 22:16:14 -0700223 mirror::Object* param = shadow_frame->GetVRegReference(arg_offset);
224 if (param == nullptr) {
225 AbortTransactionOrFail(self, "Null-pointer in Class.newInstance.");
226 return;
227 }
228 mirror::Class* klass = param->AsClass();
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700229 Handle<mirror::Class> h_klass(hs.NewHandle(klass));
Andreas Gampe0f7e3d62015-03-11 13:24:35 -0700230
231 // Check that it's not null.
232 if (h_klass.Get() == nullptr) {
233 AbortTransactionOrFail(self, "Class reference is null for newInstance");
234 return;
235 }
236
237 // If we're in a transaction, class must not be finalizable (it or a superclass has a finalizer).
238 if (Runtime::Current()->IsActiveTransaction()) {
239 if (h_klass.Get()->IsFinalizable()) {
Sebastien Hertz45b15972015-04-03 16:07:05 +0200240 AbortTransactionF(self, "Class for newInstance is finalizable: '%s'",
241 PrettyClass(h_klass.Get()).c_str());
Andreas Gampe0f7e3d62015-03-11 13:24:35 -0700242 return;
243 }
244 }
245
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700246 // There are two situations in which we'll abort this run.
247 // 1) If the class isn't yet initialized and initialization fails.
248 // 2) If we can't find the default constructor. We'll postpone the exception to runtime.
249 // Note that 2) could likely be handled here, but for safety abort the transaction.
250 bool ok = false;
Mathieu Chartiere401d142015-04-22 13:56:20 -0700251 auto* cl = Runtime::Current()->GetClassLinker();
252 if (cl->EnsureInitialized(self, h_klass, true, true)) {
253 auto* cons = h_klass->FindDeclaredDirectMethod("<init>", "()V", cl->GetImagePointerSize());
254 if (cons != nullptr) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700255 Handle<mirror::Object> h_obj(hs.NewHandle(klass->AllocObject(self)));
256 CHECK(h_obj.Get() != nullptr); // We don't expect OOM at compile-time.
Mathieu Chartiere401d142015-04-22 13:56:20 -0700257 EnterInterpreterFromInvoke(self, cons, h_obj.Get(), nullptr, nullptr);
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700258 if (!self->IsExceptionPending()) {
259 result->SetL(h_obj.Get());
260 ok = true;
261 }
262 } else {
263 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
264 "Could not find default constructor for '%s'",
265 PrettyClass(h_klass.Get()).c_str());
266 }
267 }
268 if (!ok) {
Andreas Gampe068b0c02015-03-11 12:44:47 -0700269 AbortTransactionOrFail(self, "Failed in Class.newInstance for '%s' with %s",
270 PrettyClass(h_klass.Get()).c_str(),
271 PrettyTypeOf(self->GetException()).c_str());
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700272 }
273}
274
Andreas Gampe799681b2015-05-15 19:24:12 -0700275void UnstartedRuntime::UnstartedClassGetDeclaredField(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700276 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700277 // Special managed code cut-out to allow field lookup in a un-started runtime that'd fail
278 // going the reflective Dex way.
279 mirror::Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
280 mirror::String* name2 = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
Mathieu Chartierc7853442015-03-27 14:35:38 -0700281 ArtField* found = nullptr;
Mathieu Chartier54d220e2015-07-30 16:20:06 -0700282 for (ArtField& field : klass->GetIFields()) {
283 if (name2->Equals(field.GetName())) {
284 found = &field;
Mathieu Chartierc7853442015-03-27 14:35:38 -0700285 break;
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700286 }
287 }
288 if (found == nullptr) {
Mathieu Chartier54d220e2015-07-30 16:20:06 -0700289 for (ArtField& field : klass->GetSFields()) {
290 if (name2->Equals(field.GetName())) {
291 found = &field;
Mathieu Chartierc7853442015-03-27 14:35:38 -0700292 break;
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700293 }
294 }
295 }
Andreas Gampe068b0c02015-03-11 12:44:47 -0700296 if (found == nullptr) {
297 AbortTransactionOrFail(self, "Failed to find field in Class.getDeclaredField in un-started "
298 " runtime. name=%s class=%s", name2->ToModifiedUtf8().c_str(),
299 PrettyDescriptor(klass).c_str());
300 return;
301 }
Mathieu Chartierdaaf3262015-03-24 13:30:28 -0700302 if (Runtime::Current()->IsActiveTransaction()) {
303 result->SetL(mirror::Field::CreateFromArtField<true>(self, found, true));
304 } else {
305 result->SetL(mirror::Field::CreateFromArtField<false>(self, found, true));
306 }
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700307}
308
Andreas Gampebc4d2182016-02-22 10:03:12 -0800309// This is required for Enum(Set) code, as that uses reflection to inspect enum classes.
310void UnstartedRuntime::UnstartedClassGetDeclaredMethod(
311 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
312 // Special managed code cut-out to allow method lookup in a un-started runtime.
313 mirror::Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
314 if (klass == nullptr) {
315 ThrowNullPointerExceptionForMethodAccess(shadow_frame->GetMethod(), InvokeType::kVirtual);
316 return;
317 }
318 mirror::String* name = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
319 mirror::ObjectArray<mirror::Class>* args =
320 shadow_frame->GetVRegReference(arg_offset + 2)->AsObjectArray<mirror::Class>();
321 if (Runtime::Current()->IsActiveTransaction()) {
322 result->SetL(mirror::Class::GetDeclaredMethodInternal<true>(self, klass, name, args));
323 } else {
324 result->SetL(mirror::Class::GetDeclaredMethodInternal<false>(self, klass, name, args));
325 }
326}
327
Andreas Gampe6039e562016-04-05 18:18:43 -0700328// Special managed code cut-out to allow constructor lookup in a un-started runtime.
329void UnstartedRuntime::UnstartedClassGetDeclaredConstructor(
330 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
331 mirror::Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
332 if (klass == nullptr) {
333 ThrowNullPointerExceptionForMethodAccess(shadow_frame->GetMethod(), InvokeType::kVirtual);
334 return;
335 }
336 mirror::ObjectArray<mirror::Class>* args =
337 shadow_frame->GetVRegReference(arg_offset + 1)->AsObjectArray<mirror::Class>();
338 if (Runtime::Current()->IsActiveTransaction()) {
339 result->SetL(mirror::Class::GetDeclaredConstructorInternal<true>(self, klass, args));
340 } else {
341 result->SetL(mirror::Class::GetDeclaredConstructorInternal<false>(self, klass, args));
342 }
343}
344
Andreas Gampe633750c2016-02-19 10:49:50 -0800345void UnstartedRuntime::UnstartedClassGetEnclosingClass(
346 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
347 StackHandleScope<1> hs(self);
348 Handle<mirror::Class> klass(hs.NewHandle(shadow_frame->GetVRegReference(arg_offset)->AsClass()));
349 if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
350 result->SetL(nullptr);
351 }
352 result->SetL(klass->GetDexFile().GetEnclosingClass(klass));
353}
354
Andreas Gampeeb8b0ae2016-04-13 17:58:05 -0700355static std::unique_ptr<MemMap> FindAndExtractEntry(const std::string& jar_file,
356 const char* entry_name,
357 size_t* size,
358 std::string* error_msg) {
359 CHECK(size != nullptr);
360
361 std::unique_ptr<ZipArchive> zip_archive(ZipArchive::Open(jar_file.c_str(), error_msg));
362 if (zip_archive == nullptr) {
363 return nullptr;;
364 }
365 std::unique_ptr<ZipEntry> zip_entry(zip_archive->Find(entry_name, error_msg));
366 if (zip_entry == nullptr) {
367 return nullptr;
368 }
369 std::unique_ptr<MemMap> tmp_map(
370 zip_entry->ExtractToMemMap(jar_file.c_str(), entry_name, error_msg));
371 if (tmp_map == nullptr) {
372 return nullptr;
373 }
374
375 // OK, from here everything seems fine.
376 *size = zip_entry->GetUncompressedLength();
377 return tmp_map;
378}
379
380static void GetResourceAsStream(Thread* self,
381 ShadowFrame* shadow_frame,
382 JValue* result,
383 size_t arg_offset) SHARED_REQUIRES(Locks::mutator_lock_) {
384 mirror::Object* resource_obj = shadow_frame->GetVRegReference(arg_offset + 1);
385 if (resource_obj == nullptr) {
386 AbortTransactionOrFail(self, "null name for getResourceAsStream");
387 return;
388 }
389 CHECK(resource_obj->IsString());
390 mirror::String* resource_name = resource_obj->AsString();
391
392 std::string resource_name_str = resource_name->ToModifiedUtf8();
393 if (resource_name_str.empty() || resource_name_str == "/") {
394 AbortTransactionOrFail(self,
395 "Unsupported name %s for getResourceAsStream",
396 resource_name_str.c_str());
397 return;
398 }
399 const char* resource_cstr = resource_name_str.c_str();
400 if (resource_cstr[0] == '/') {
401 resource_cstr++;
402 }
403
404 Runtime* runtime = Runtime::Current();
405
406 std::vector<std::string> split;
407 Split(runtime->GetBootClassPathString(), ':', &split);
408 if (split.empty()) {
409 AbortTransactionOrFail(self,
410 "Boot classpath not set or split error:: %s",
411 runtime->GetBootClassPathString().c_str());
412 return;
413 }
414
415 std::unique_ptr<MemMap> mem_map;
416 size_t map_size;
417 std::string last_error_msg; // Only store the last message (we could concatenate).
418
419 for (const std::string& jar_file : split) {
420 mem_map = FindAndExtractEntry(jar_file, resource_cstr, &map_size, &last_error_msg);
421 if (mem_map != nullptr) {
422 break;
423 }
424 }
425
426 if (mem_map == nullptr) {
427 // Didn't find it. There's a good chance this will be the same at runtime, but still
428 // conservatively abort the transaction here.
429 AbortTransactionOrFail(self,
430 "Could not find resource %s. Last error was %s.",
431 resource_name_str.c_str(),
432 last_error_msg.c_str());
433 return;
434 }
435
436 StackHandleScope<3> hs(self);
437
438 // Create byte array for content.
439 Handle<mirror::ByteArray> h_array(hs.NewHandle(mirror::ByteArray::Alloc(self, map_size)));
440 if (h_array.Get() == nullptr) {
441 AbortTransactionOrFail(self, "Could not find/create byte array class");
442 return;
443 }
444 // Copy in content.
445 memcpy(h_array->GetData(), mem_map->Begin(), map_size);
446 // Be proactive releasing memory.
447 mem_map.release();
448
449 // Create a ByteArrayInputStream.
450 Handle<mirror::Class> h_class(hs.NewHandle(
451 runtime->GetClassLinker()->FindClass(self,
452 "Ljava/io/ByteArrayInputStream;",
453 ScopedNullHandle<mirror::ClassLoader>())));
454 if (h_class.Get() == nullptr) {
455 AbortTransactionOrFail(self, "Could not find ByteArrayInputStream class");
456 return;
457 }
458 if (!runtime->GetClassLinker()->EnsureInitialized(self, h_class, true, true)) {
459 AbortTransactionOrFail(self, "Could not initialize ByteArrayInputStream class");
460 return;
461 }
462
463 Handle<mirror::Object> h_obj(hs.NewHandle(h_class->AllocObject(self)));
464 if (h_obj.Get() == nullptr) {
465 AbortTransactionOrFail(self, "Could not allocate ByteArrayInputStream object");
466 return;
467 }
468
469 auto* cl = Runtime::Current()->GetClassLinker();
470 ArtMethod* constructor = h_class->FindDeclaredDirectMethod(
471 "<init>", "([B)V", cl->GetImagePointerSize());
472 if (constructor == nullptr) {
473 AbortTransactionOrFail(self, "Could not find ByteArrayInputStream constructor");
474 return;
475 }
476
477 uint32_t args[1];
478 args[0] = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(h_array.Get()));
479 EnterInterpreterFromInvoke(self, constructor, h_obj.Get(), args, nullptr);
480
481 if (self->IsExceptionPending()) {
482 AbortTransactionOrFail(self, "Could not run ByteArrayInputStream constructor");
483 return;
484 }
485
486 result->SetL(h_obj.Get());
487}
488
489void UnstartedRuntime::UnstartedClassLoaderGetResourceAsStream(
490 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
491 {
492 mirror::Object* this_obj = shadow_frame->GetVRegReference(arg_offset);
493 CHECK(this_obj != nullptr);
494 CHECK(this_obj->IsClassLoader());
495
496 StackHandleScope<1> hs(self);
497 Handle<mirror::Class> this_classloader_class(hs.NewHandle(this_obj->GetClass()));
498
499 if (self->DecodeJObject(WellKnownClasses::java_lang_BootClassLoader) !=
500 this_classloader_class.Get()) {
501 AbortTransactionOrFail(self,
502 "Unsupported classloader type %s for getResourceAsStream",
503 PrettyClass(this_classloader_class.Get()).c_str());
504 return;
505 }
506 }
507
508 GetResourceAsStream(self, shadow_frame, result, arg_offset);
509}
510
Andreas Gampe799681b2015-05-15 19:24:12 -0700511void UnstartedRuntime::UnstartedVmClassLoaderFindLoadedClass(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700512 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700513 mirror::String* class_name = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
514 mirror::ClassLoader* class_loader =
515 down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset));
516 StackHandleScope<2> hs(self);
517 Handle<mirror::String> h_class_name(hs.NewHandle(class_name));
518 Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(class_loader));
519 UnstartedRuntimeFindClass(self, h_class_name, h_class_loader, result,
520 "VMClassLoader.findLoadedClass", false, false);
521 // This might have an error pending. But semantics are to just return null.
522 if (self->IsExceptionPending()) {
523 // If it is an InternalError, keep it. See CheckExceptionGenerateClassNotFound.
524 std::string type(PrettyTypeOf(self->GetException()));
525 if (type != "java.lang.InternalError") {
526 self->ClearException();
527 }
528 }
529}
530
Mathieu Chartiere401d142015-04-22 13:56:20 -0700531void UnstartedRuntime::UnstartedVoidLookupType(
532 Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame ATTRIBUTE_UNUSED, JValue* result,
533 size_t arg_offset ATTRIBUTE_UNUSED) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700534 result->SetL(Runtime::Current()->GetClassLinker()->FindPrimitiveClass('V'));
535}
536
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700537// Arraycopy emulation.
538// Note: we can't use any fast copy functions, as they are not available under transaction.
539
540template <typename T>
541static void PrimitiveArrayCopy(Thread* self,
542 mirror::Array* src_array, int32_t src_pos,
543 mirror::Array* dst_array, int32_t dst_pos,
544 int32_t length)
Mathieu Chartier90443472015-07-16 20:32:27 -0700545 SHARED_REQUIRES(Locks::mutator_lock_) {
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700546 if (src_array->GetClass()->GetComponentType() != dst_array->GetClass()->GetComponentType()) {
547 AbortTransactionOrFail(self, "Types mismatched in arraycopy: %s vs %s.",
548 PrettyDescriptor(src_array->GetClass()->GetComponentType()).c_str(),
549 PrettyDescriptor(dst_array->GetClass()->GetComponentType()).c_str());
550 return;
551 }
552 mirror::PrimitiveArray<T>* src = down_cast<mirror::PrimitiveArray<T>*>(src_array);
553 mirror::PrimitiveArray<T>* dst = down_cast<mirror::PrimitiveArray<T>*>(dst_array);
554 const bool copy_forward = (dst_pos < src_pos) || (dst_pos - src_pos >= length);
555 if (copy_forward) {
556 for (int32_t i = 0; i < length; ++i) {
557 dst->Set(dst_pos + i, src->Get(src_pos + i));
558 }
559 } else {
560 for (int32_t i = 1; i <= length; ++i) {
561 dst->Set(dst_pos + length - i, src->Get(src_pos + length - i));
562 }
563 }
564}
565
Andreas Gampe799681b2015-05-15 19:24:12 -0700566void UnstartedRuntime::UnstartedSystemArraycopy(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700567 Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700568 // Special case array copying without initializing System.
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700569 jint src_pos = shadow_frame->GetVReg(arg_offset + 1);
570 jint dst_pos = shadow_frame->GetVReg(arg_offset + 3);
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700571 jint length = shadow_frame->GetVReg(arg_offset + 4);
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700572
Andreas Gampe85a098a2016-03-31 13:30:53 -0700573 mirror::Object* src_obj = shadow_frame->GetVRegReference(arg_offset);
574 mirror::Object* dst_obj = shadow_frame->GetVRegReference(arg_offset + 2);
575 // Null checking. For simplicity, abort transaction.
576 if (src_obj == nullptr) {
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700577 AbortTransactionOrFail(self, "src is null in arraycopy.");
578 return;
579 }
Andreas Gampe85a098a2016-03-31 13:30:53 -0700580 if (dst_obj == nullptr) {
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700581 AbortTransactionOrFail(self, "dst is null in arraycopy.");
582 return;
583 }
Andreas Gampe85a098a2016-03-31 13:30:53 -0700584 // Test for arrayness. Throw ArrayStoreException.
585 if (!src_obj->IsArrayInstance() || !dst_obj->IsArrayInstance()) {
586 self->ThrowNewException("Ljava/lang/ArrayStoreException;", "src or trg is not an array");
587 return;
588 }
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700589
Andreas Gampe85a098a2016-03-31 13:30:53 -0700590 mirror::Array* src_array = src_obj->AsArray();
591 mirror::Array* dst_array = dst_obj->AsArray();
592
593 // Bounds checking. Throw IndexOutOfBoundsException.
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700594 if (UNLIKELY(src_pos < 0) || UNLIKELY(dst_pos < 0) || UNLIKELY(length < 0) ||
595 UNLIKELY(src_pos > src_array->GetLength() - length) ||
596 UNLIKELY(dst_pos > dst_array->GetLength() - length)) {
Andreas Gampe85a098a2016-03-31 13:30:53 -0700597 self->ThrowNewExceptionF("Ljava/lang/IndexOutOfBoundsException;",
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700598 "src.length=%d srcPos=%d dst.length=%d dstPos=%d length=%d",
599 src_array->GetLength(), src_pos, dst_array->GetLength(), dst_pos,
600 length);
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700601 return;
602 }
603
604 // Type checking.
605 mirror::Class* src_type = shadow_frame->GetVRegReference(arg_offset)->GetClass()->
606 GetComponentType();
607
608 if (!src_type->IsPrimitive()) {
609 // Check that the second type is not primitive.
610 mirror::Class* trg_type = shadow_frame->GetVRegReference(arg_offset + 2)->GetClass()->
611 GetComponentType();
612 if (trg_type->IsPrimitiveInt()) {
613 AbortTransactionOrFail(self, "Type mismatch in arraycopy: %s vs %s",
614 PrettyDescriptor(src_array->GetClass()->GetComponentType()).c_str(),
615 PrettyDescriptor(dst_array->GetClass()->GetComponentType()).c_str());
616 return;
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700617 }
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700618
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700619 mirror::ObjectArray<mirror::Object>* src = src_array->AsObjectArray<mirror::Object>();
620 mirror::ObjectArray<mirror::Object>* dst = dst_array->AsObjectArray<mirror::Object>();
621 if (src == dst) {
622 // Can overlap, but not have type mismatches.
Andreas Gampe85a098a2016-03-31 13:30:53 -0700623 // We cannot use ObjectArray::MemMove here, as it doesn't support transactions.
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700624 const bool copy_forward = (dst_pos < src_pos) || (dst_pos - src_pos >= length);
625 if (copy_forward) {
626 for (int32_t i = 0; i < length; ++i) {
627 dst->Set(dst_pos + i, src->Get(src_pos + i));
628 }
629 } else {
630 for (int32_t i = 1; i <= length; ++i) {
631 dst->Set(dst_pos + length - i, src->Get(src_pos + length - i));
632 }
633 }
634 } else {
Andreas Gampe85a098a2016-03-31 13:30:53 -0700635 // We're being lazy here. Optimally this could be a memcpy (if component types are
636 // assignable), but the ObjectArray implementation doesn't support transactions. The
637 // checking version, however, does.
638 if (Runtime::Current()->IsActiveTransaction()) {
639 dst->AssignableCheckingMemcpy<true>(
640 dst_pos, src, src_pos, length, true /* throw_exception */);
641 } else {
642 dst->AssignableCheckingMemcpy<false>(
643 dst_pos, src, src_pos, length, true /* throw_exception */);
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700644 }
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700645 }
Andreas Gampe5c9af612016-04-05 14:16:10 -0700646 } else if (src_type->IsPrimitiveByte()) {
647 PrimitiveArrayCopy<uint8_t>(self, src_array, src_pos, dst_array, dst_pos, length);
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700648 } else if (src_type->IsPrimitiveChar()) {
649 PrimitiveArrayCopy<uint16_t>(self, src_array, src_pos, dst_array, dst_pos, length);
650 } else if (src_type->IsPrimitiveInt()) {
651 PrimitiveArrayCopy<int32_t>(self, src_array, src_pos, dst_array, dst_pos, length);
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700652 } else {
Andreas Gampe068b0c02015-03-11 12:44:47 -0700653 AbortTransactionOrFail(self, "Unimplemented System.arraycopy for type '%s'",
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700654 PrettyDescriptor(src_type).c_str());
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700655 }
656}
657
Andreas Gampe5c9af612016-04-05 14:16:10 -0700658void UnstartedRuntime::UnstartedSystemArraycopyByte(
659 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
660 // Just forward.
661 UnstartedRuntime::UnstartedSystemArraycopy(self, shadow_frame, result, arg_offset);
662}
663
Andreas Gampe799681b2015-05-15 19:24:12 -0700664void UnstartedRuntime::UnstartedSystemArraycopyChar(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700665 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe799681b2015-05-15 19:24:12 -0700666 // Just forward.
667 UnstartedRuntime::UnstartedSystemArraycopy(self, shadow_frame, result, arg_offset);
668}
669
670void UnstartedRuntime::UnstartedSystemArraycopyInt(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700671 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe799681b2015-05-15 19:24:12 -0700672 // Just forward.
673 UnstartedRuntime::UnstartedSystemArraycopy(self, shadow_frame, result, arg_offset);
674}
675
Narayan Kamath34a316f2016-03-30 13:11:18 +0100676void UnstartedRuntime::UnstartedSystemGetSecurityManager(
677 Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame ATTRIBUTE_UNUSED,
678 JValue* result, size_t arg_offset ATTRIBUTE_UNUSED) {
679 result->SetL(nullptr);
680}
681
Andreas Gamped4fa9f42016-04-13 14:53:23 -0700682static constexpr const char* kAndroidHardcodedSystemPropertiesFieldName = "STATIC_PROPERTIES";
683
684static void GetSystemProperty(Thread* self,
685 ShadowFrame* shadow_frame,
686 JValue* result,
687 size_t arg_offset,
688 bool is_default_version)
689 SHARED_REQUIRES(Locks::mutator_lock_) {
690 StackHandleScope<4> hs(self);
691 Handle<mirror::String> h_key(
692 hs.NewHandle(reinterpret_cast<mirror::String*>(shadow_frame->GetVRegReference(arg_offset))));
693 if (h_key.Get() == nullptr) {
694 AbortTransactionOrFail(self, "getProperty key was null");
695 return;
696 }
697
698 // This is overall inefficient, but reflecting the values here is not great, either. So
699 // for simplicity, and with the assumption that the number of getProperty calls is not
700 // too great, just iterate each time.
701
702 // Get the storage class.
703 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
704 Handle<mirror::Class> h_props_class(hs.NewHandle(
705 class_linker->FindClass(self,
706 "Ljava/lang/AndroidHardcodedSystemProperties;",
707 ScopedNullHandle<mirror::ClassLoader>())));
708 if (h_props_class.Get() == nullptr) {
709 AbortTransactionOrFail(self, "Could not find AndroidHardcodedSystemProperties");
710 return;
711 }
712 if (!class_linker->EnsureInitialized(self, h_props_class, true, true)) {
713 AbortTransactionOrFail(self, "Could not initialize AndroidHardcodedSystemProperties");
714 return;
715 }
716
717 // Get the storage array.
718 ArtField* static_properties =
719 h_props_class->FindDeclaredStaticField(kAndroidHardcodedSystemPropertiesFieldName,
720 "[[Ljava/lang/String;");
721 if (static_properties == nullptr) {
722 AbortTransactionOrFail(self,
723 "Could not find %s field",
724 kAndroidHardcodedSystemPropertiesFieldName);
725 return;
726 }
727 Handle<mirror::ObjectArray<mirror::ObjectArray<mirror::String>>> h_2string_array(
728 hs.NewHandle(reinterpret_cast<mirror::ObjectArray<mirror::ObjectArray<mirror::String>>*>(
729 static_properties->GetObject(h_props_class.Get()))));
730 if (h_2string_array.Get() == nullptr) {
731 AbortTransactionOrFail(self, "Field %s is null", kAndroidHardcodedSystemPropertiesFieldName);
732 return;
733 }
734
735 // Iterate over it.
736 const int32_t prop_count = h_2string_array->GetLength();
737 // Use the third handle as mutable.
738 MutableHandle<mirror::ObjectArray<mirror::String>> h_string_array(
739 hs.NewHandle<mirror::ObjectArray<mirror::String>>(nullptr));
740 for (int32_t i = 0; i < prop_count; ++i) {
741 h_string_array.Assign(h_2string_array->Get(i));
742 if (h_string_array.Get() == nullptr ||
743 h_string_array->GetLength() != 2 ||
744 h_string_array->Get(0) == nullptr) {
745 AbortTransactionOrFail(self,
746 "Unexpected content of %s",
747 kAndroidHardcodedSystemPropertiesFieldName);
748 return;
749 }
750 if (h_key->Equals(h_string_array->Get(0))) {
751 // Found a value.
752 if (h_string_array->Get(1) == nullptr && is_default_version) {
753 // Null is being delegated to the default map, and then resolved to the given default value.
754 // As there's no default map, return the given value.
755 result->SetL(shadow_frame->GetVRegReference(arg_offset + 1));
756 } else {
757 result->SetL(h_string_array->Get(1));
758 }
759 return;
760 }
761 }
762
763 // Key is not supported.
764 AbortTransactionOrFail(self, "getProperty key %s not supported", h_key->ToModifiedUtf8().c_str());
765}
766
767void UnstartedRuntime::UnstartedSystemGetProperty(
768 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
769 GetSystemProperty(self, shadow_frame, result, arg_offset, false);
770}
771
772void UnstartedRuntime::UnstartedSystemGetPropertyWithDefault(
773 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
774 GetSystemProperty(self, shadow_frame, result, arg_offset, true);
775}
776
Andreas Gampe799681b2015-05-15 19:24:12 -0700777void UnstartedRuntime::UnstartedThreadLocalGet(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700778 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset ATTRIBUTE_UNUSED) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700779 std::string caller(PrettyMethod(shadow_frame->GetLink()->GetMethod()));
780 bool ok = false;
Narayan Kamatha1e93122016-03-30 15:41:54 +0100781 if (caller == "void java.lang.FloatingDecimal.developLongDigits(int, long, long)" ||
782 caller == "java.lang.String java.lang.FloatingDecimal.toJavaFormatString()") {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700783 // Allocate non-threadlocal buffer.
Narayan Kamatha1e93122016-03-30 15:41:54 +0100784 result->SetL(mirror::CharArray::Alloc(self, 26));
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700785 ok = true;
Narayan Kamatha1e93122016-03-30 15:41:54 +0100786 } else if (caller ==
787 "java.lang.FloatingDecimal java.lang.FloatingDecimal.getThreadLocalInstance()") {
788 // Allocate new object.
789 StackHandleScope<2> hs(self);
790 Handle<mirror::Class> h_real_to_string_class(hs.NewHandle(
791 shadow_frame->GetLink()->GetMethod()->GetDeclaringClass()));
792 Handle<mirror::Object> h_real_to_string_obj(hs.NewHandle(
793 h_real_to_string_class->AllocObject(self)));
794 if (h_real_to_string_obj.Get() != nullptr) {
795 auto* cl = Runtime::Current()->GetClassLinker();
796 ArtMethod* init_method = h_real_to_string_class->FindDirectMethod(
797 "<init>", "()V", cl->GetImagePointerSize());
798 if (init_method == nullptr) {
799 h_real_to_string_class->DumpClass(LOG(FATAL), mirror::Class::kDumpClassFullDetail);
800 } else {
801 JValue invoke_result;
802 EnterInterpreterFromInvoke(self, init_method, h_real_to_string_obj.Get(), nullptr,
803 nullptr);
804 if (!self->IsExceptionPending()) {
805 result->SetL(h_real_to_string_obj.Get());
806 ok = true;
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700807 }
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700808 }
809 }
810 }
811
812 if (!ok) {
Andreas Gampe068b0c02015-03-11 12:44:47 -0700813 AbortTransactionOrFail(self, "Could not create RealToString object");
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700814 }
815}
816
Sergio Giro83261202016-04-11 20:49:20 +0100817void UnstartedRuntime::UnstartedMathCeil(
818 Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe89e3b482016-04-12 18:07:36 -0700819 result->SetD(ceil(shadow_frame->GetVRegDouble(arg_offset)));
Sergio Giro83261202016-04-11 20:49:20 +0100820}
821
822void UnstartedRuntime::UnstartedMathFloor(
823 Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe89e3b482016-04-12 18:07:36 -0700824 result->SetD(floor(shadow_frame->GetVRegDouble(arg_offset)));
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700825}
826
Andreas Gampe799681b2015-05-15 19:24:12 -0700827void UnstartedRuntime::UnstartedObjectHashCode(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700828 Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700829 mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset);
830 result->SetI(obj->IdentityHashCode());
831}
832
Andreas Gampe799681b2015-05-15 19:24:12 -0700833void UnstartedRuntime::UnstartedDoubleDoubleToRawLongBits(
Andreas Gampedd9d0552015-03-09 12:57:41 -0700834 Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700835 double in = shadow_frame->GetVRegDouble(arg_offset);
Roland Levillainda4d79b2015-03-24 14:36:11 +0000836 result->SetJ(bit_cast<int64_t, double>(in));
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700837}
838
Andreas Gampedd9d0552015-03-09 12:57:41 -0700839static mirror::Object* GetDexFromDexCache(Thread* self, mirror::DexCache* dex_cache)
Mathieu Chartier90443472015-07-16 20:32:27 -0700840 SHARED_REQUIRES(Locks::mutator_lock_) {
Andreas Gampedd9d0552015-03-09 12:57:41 -0700841 const DexFile* dex_file = dex_cache->GetDexFile();
842 if (dex_file == nullptr) {
843 return nullptr;
844 }
845
846 // Create the direct byte buffer.
847 JNIEnv* env = self->GetJniEnv();
848 DCHECK(env != nullptr);
849 void* address = const_cast<void*>(reinterpret_cast<const void*>(dex_file->Begin()));
Andreas Gampeaacc25d2015-04-01 14:49:06 -0700850 ScopedLocalRef<jobject> byte_buffer(env, env->NewDirectByteBuffer(address, dex_file->Size()));
851 if (byte_buffer.get() == nullptr) {
Andreas Gampedd9d0552015-03-09 12:57:41 -0700852 DCHECK(self->IsExceptionPending());
853 return nullptr;
854 }
855
856 jvalue args[1];
Andreas Gampeaacc25d2015-04-01 14:49:06 -0700857 args[0].l = byte_buffer.get();
858
859 ScopedLocalRef<jobject> dex(env, env->CallStaticObjectMethodA(
860 WellKnownClasses::com_android_dex_Dex,
861 WellKnownClasses::com_android_dex_Dex_create,
862 args));
863
864 return self->DecodeJObject(dex.get());
Andreas Gampedd9d0552015-03-09 12:57:41 -0700865}
866
Andreas Gampe799681b2015-05-15 19:24:12 -0700867void UnstartedRuntime::UnstartedDexCacheGetDexNative(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700868 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampedd9d0552015-03-09 12:57:41 -0700869 // We will create the Dex object, but the image writer will release it before creating the
870 // art file.
871 mirror::Object* src = shadow_frame->GetVRegReference(arg_offset);
872 bool have_dex = false;
873 if (src != nullptr) {
874 mirror::Object* dex = GetDexFromDexCache(self, reinterpret_cast<mirror::DexCache*>(src));
875 if (dex != nullptr) {
876 have_dex = true;
877 result->SetL(dex);
878 }
879 }
880 if (!have_dex) {
881 self->ClearException();
Sebastien Hertz2fd7e692015-04-02 11:11:19 +0200882 Runtime::Current()->AbortTransactionAndThrowAbortError(self, "Could not create Dex object");
Andreas Gampedd9d0552015-03-09 12:57:41 -0700883 }
884}
885
886static void UnstartedMemoryPeek(
887 Primitive::Type type, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
888 int64_t address = shadow_frame->GetVRegLong(arg_offset);
889 // TODO: Check that this is in the heap somewhere. Otherwise we will segfault instead of
890 // aborting the transaction.
891
892 switch (type) {
893 case Primitive::kPrimByte: {
894 result->SetB(*reinterpret_cast<int8_t*>(static_cast<intptr_t>(address)));
895 return;
896 }
897
898 case Primitive::kPrimShort: {
Andreas Gampe799681b2015-05-15 19:24:12 -0700899 typedef int16_t unaligned_short __attribute__ ((aligned (1)));
900 result->SetS(*reinterpret_cast<unaligned_short*>(static_cast<intptr_t>(address)));
Andreas Gampedd9d0552015-03-09 12:57:41 -0700901 return;
902 }
903
904 case Primitive::kPrimInt: {
Andreas Gampe799681b2015-05-15 19:24:12 -0700905 typedef int32_t unaligned_int __attribute__ ((aligned (1)));
906 result->SetI(*reinterpret_cast<unaligned_int*>(static_cast<intptr_t>(address)));
Andreas Gampedd9d0552015-03-09 12:57:41 -0700907 return;
908 }
909
910 case Primitive::kPrimLong: {
Andreas Gampe799681b2015-05-15 19:24:12 -0700911 typedef int64_t unaligned_long __attribute__ ((aligned (1)));
912 result->SetJ(*reinterpret_cast<unaligned_long*>(static_cast<intptr_t>(address)));
Andreas Gampedd9d0552015-03-09 12:57:41 -0700913 return;
914 }
915
916 case Primitive::kPrimBoolean:
917 case Primitive::kPrimChar:
918 case Primitive::kPrimFloat:
919 case Primitive::kPrimDouble:
920 case Primitive::kPrimVoid:
921 case Primitive::kPrimNot:
922 LOG(FATAL) << "Not in the Memory API: " << type;
923 UNREACHABLE();
924 }
925 LOG(FATAL) << "Should not reach here";
926 UNREACHABLE();
927}
928
Andreas Gampe799681b2015-05-15 19:24:12 -0700929void UnstartedRuntime::UnstartedMemoryPeekByte(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700930 Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe799681b2015-05-15 19:24:12 -0700931 UnstartedMemoryPeek(Primitive::kPrimByte, shadow_frame, result, arg_offset);
932}
933
934void UnstartedRuntime::UnstartedMemoryPeekShort(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700935 Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe799681b2015-05-15 19:24:12 -0700936 UnstartedMemoryPeek(Primitive::kPrimShort, shadow_frame, result, arg_offset);
937}
938
939void UnstartedRuntime::UnstartedMemoryPeekInt(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700940 Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe799681b2015-05-15 19:24:12 -0700941 UnstartedMemoryPeek(Primitive::kPrimInt, shadow_frame, result, arg_offset);
942}
943
944void UnstartedRuntime::UnstartedMemoryPeekLong(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700945 Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe799681b2015-05-15 19:24:12 -0700946 UnstartedMemoryPeek(Primitive::kPrimLong, shadow_frame, result, arg_offset);
Andreas Gampedd9d0552015-03-09 12:57:41 -0700947}
948
949static void UnstartedMemoryPeekArray(
950 Primitive::Type type, Thread* self, ShadowFrame* shadow_frame, size_t arg_offset)
Mathieu Chartier90443472015-07-16 20:32:27 -0700951 SHARED_REQUIRES(Locks::mutator_lock_) {
Andreas Gampedd9d0552015-03-09 12:57:41 -0700952 int64_t address_long = shadow_frame->GetVRegLong(arg_offset);
953 mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset + 2);
954 if (obj == nullptr) {
Sebastien Hertz2fd7e692015-04-02 11:11:19 +0200955 Runtime::Current()->AbortTransactionAndThrowAbortError(self, "Null pointer in peekArray");
Andreas Gampedd9d0552015-03-09 12:57:41 -0700956 return;
957 }
958 mirror::Array* array = obj->AsArray();
959
960 int offset = shadow_frame->GetVReg(arg_offset + 3);
961 int count = shadow_frame->GetVReg(arg_offset + 4);
962 if (offset < 0 || offset + count > array->GetLength()) {
963 std::string error_msg(StringPrintf("Array out of bounds in peekArray: %d/%d vs %d",
964 offset, count, array->GetLength()));
Sebastien Hertz2fd7e692015-04-02 11:11:19 +0200965 Runtime::Current()->AbortTransactionAndThrowAbortError(self, error_msg.c_str());
Andreas Gampedd9d0552015-03-09 12:57:41 -0700966 return;
967 }
968
969 switch (type) {
970 case Primitive::kPrimByte: {
971 int8_t* address = reinterpret_cast<int8_t*>(static_cast<intptr_t>(address_long));
972 mirror::ByteArray* byte_array = array->AsByteArray();
973 for (int32_t i = 0; i < count; ++i, ++address) {
974 byte_array->SetWithoutChecks<true>(i + offset, *address);
975 }
976 return;
977 }
978
979 case Primitive::kPrimShort:
980 case Primitive::kPrimInt:
981 case Primitive::kPrimLong:
982 LOG(FATAL) << "Type unimplemented for Memory Array API, should not reach here: " << type;
983 UNREACHABLE();
984
985 case Primitive::kPrimBoolean:
986 case Primitive::kPrimChar:
987 case Primitive::kPrimFloat:
988 case Primitive::kPrimDouble:
989 case Primitive::kPrimVoid:
990 case Primitive::kPrimNot:
991 LOG(FATAL) << "Not in the Memory API: " << type;
992 UNREACHABLE();
993 }
994 LOG(FATAL) << "Should not reach here";
995 UNREACHABLE();
996}
997
Andreas Gampe799681b2015-05-15 19:24:12 -0700998void UnstartedRuntime::UnstartedMemoryPeekByteArray(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700999 Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset) {
Andreas Gampe799681b2015-05-15 19:24:12 -07001000 UnstartedMemoryPeekArray(Primitive::kPrimByte, self, shadow_frame, arg_offset);
Andreas Gampedd9d0552015-03-09 12:57:41 -07001001}
1002
Andreas Gampef778eb22015-04-13 14:17:09 -07001003// This allows reading security.properties in an unstarted runtime and initialize Security.
Andreas Gampe799681b2015-05-15 19:24:12 -07001004void UnstartedRuntime::UnstartedSecurityGetSecurityPropertiesReader(
Mathieu Chartiere401d142015-04-22 13:56:20 -07001005 Thread* self, ShadowFrame* shadow_frame ATTRIBUTE_UNUSED, JValue* result,
1006 size_t arg_offset ATTRIBUTE_UNUSED) {
Andreas Gampef778eb22015-04-13 14:17:09 -07001007 Runtime* runtime = Runtime::Current();
Andreas Gampee0f633e2016-03-29 19:33:56 -07001008
1009 std::vector<std::string> split;
1010 Split(runtime->GetBootClassPathString(), ':', &split);
1011 if (split.empty()) {
1012 AbortTransactionOrFail(self,
1013 "Boot classpath not set or split error:: %s",
1014 runtime->GetBootClassPathString().c_str());
1015 return;
1016 }
1017 const std::string& source = split[0];
1018
Andreas Gampef778eb22015-04-13 14:17:09 -07001019 mirror::String* string_data;
1020
1021 // Use a block to enclose the I/O and MemMap code so buffers are released early.
1022 {
1023 std::string error_msg;
Andreas Gampee0f633e2016-03-29 19:33:56 -07001024 std::unique_ptr<ZipArchive> zip_archive(ZipArchive::Open(source.c_str(), &error_msg));
Andreas Gampef778eb22015-04-13 14:17:09 -07001025 if (zip_archive.get() == nullptr) {
Andreas Gampee0f633e2016-03-29 19:33:56 -07001026 AbortTransactionOrFail(self,
1027 "Could not open zip file %s: %s",
1028 source.c_str(),
Andreas Gampef778eb22015-04-13 14:17:09 -07001029 error_msg.c_str());
1030 return;
1031 }
1032 std::unique_ptr<ZipEntry> zip_entry(zip_archive->Find("java/security/security.properties",
1033 &error_msg));
1034 if (zip_entry.get() == nullptr) {
Andreas Gampee0f633e2016-03-29 19:33:56 -07001035 AbortTransactionOrFail(self,
1036 "Could not find security.properties file in %s: %s",
1037 source.c_str(),
1038 error_msg.c_str());
Andreas Gampef778eb22015-04-13 14:17:09 -07001039 return;
1040 }
Andreas Gampee0f633e2016-03-29 19:33:56 -07001041 std::unique_ptr<MemMap> map(zip_entry->ExtractToMemMap(source.c_str(),
Andreas Gampef778eb22015-04-13 14:17:09 -07001042 "java/security/security.properties",
1043 &error_msg));
1044 if (map.get() == nullptr) {
Andreas Gampee0f633e2016-03-29 19:33:56 -07001045 AbortTransactionOrFail(self,
1046 "Could not unzip security.properties file in %s: %s",
1047 source.c_str(),
1048 error_msg.c_str());
Andreas Gampef778eb22015-04-13 14:17:09 -07001049 return;
1050 }
1051
1052 uint32_t length = zip_entry->GetUncompressedLength();
1053 std::unique_ptr<char[]> tmp(new char[length + 1]);
1054 memcpy(tmp.get(), map->Begin(), length);
1055 tmp.get()[length] = 0; // null terminator
1056
1057 string_data = mirror::String::AllocFromModifiedUtf8(self, tmp.get());
1058 }
1059
1060 if (string_data == nullptr) {
Andreas Gampee0f633e2016-03-29 19:33:56 -07001061 AbortTransactionOrFail(self, "Could not create string from file content of %s", source.c_str());
Andreas Gampef778eb22015-04-13 14:17:09 -07001062 return;
1063 }
1064
1065 // Create a StringReader.
1066 StackHandleScope<3> hs(self);
1067 Handle<mirror::String> h_string(hs.NewHandle(string_data));
1068
1069 Handle<mirror::Class> h_class(hs.NewHandle(
1070 runtime->GetClassLinker()->FindClass(self,
1071 "Ljava/io/StringReader;",
Mathieu Chartier9865bde2015-12-21 09:58:16 -08001072 ScopedNullHandle<mirror::ClassLoader>())));
Andreas Gampef778eb22015-04-13 14:17:09 -07001073 if (h_class.Get() == nullptr) {
1074 AbortTransactionOrFail(self, "Could not find StringReader class");
1075 return;
1076 }
1077
1078 if (!runtime->GetClassLinker()->EnsureInitialized(self, h_class, true, true)) {
1079 AbortTransactionOrFail(self, "Could not initialize StringReader class");
1080 return;
1081 }
1082
1083 Handle<mirror::Object> h_obj(hs.NewHandle(h_class->AllocObject(self)));
1084 if (h_obj.Get() == nullptr) {
1085 AbortTransactionOrFail(self, "Could not allocate StringReader object");
1086 return;
1087 }
1088
Mathieu Chartiere401d142015-04-22 13:56:20 -07001089 auto* cl = Runtime::Current()->GetClassLinker();
1090 ArtMethod* constructor = h_class->FindDeclaredDirectMethod(
1091 "<init>", "(Ljava/lang/String;)V", cl->GetImagePointerSize());
Andreas Gampef778eb22015-04-13 14:17:09 -07001092 if (constructor == nullptr) {
1093 AbortTransactionOrFail(self, "Could not find StringReader constructor");
1094 return;
1095 }
1096
1097 uint32_t args[1];
1098 args[0] = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(h_string.Get()));
1099 EnterInterpreterFromInvoke(self, constructor, h_obj.Get(), args, nullptr);
1100
1101 if (self->IsExceptionPending()) {
1102 AbortTransactionOrFail(self, "Could not run StringReader constructor");
1103 return;
1104 }
1105
1106 result->SetL(h_obj.Get());
1107}
1108
Kenny Root1c9e61c2015-05-14 15:58:17 -07001109// This allows reading the new style of String objects during compilation.
Andreas Gampe799681b2015-05-15 19:24:12 -07001110void UnstartedRuntime::UnstartedStringGetCharsNoCheck(
Mathieu Chartiere401d142015-04-22 13:56:20 -07001111 Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset) {
Kenny Root1c9e61c2015-05-14 15:58:17 -07001112 jint start = shadow_frame->GetVReg(arg_offset + 1);
1113 jint end = shadow_frame->GetVReg(arg_offset + 2);
1114 jint index = shadow_frame->GetVReg(arg_offset + 4);
1115 mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
1116 if (string == nullptr) {
1117 AbortTransactionOrFail(self, "String.getCharsNoCheck with null object");
1118 return;
1119 }
Kenny Root57f91e82015-05-14 15:58:17 -07001120 DCHECK_GE(start, 0);
1121 DCHECK_GE(end, string->GetLength());
Kenny Root1c9e61c2015-05-14 15:58:17 -07001122 StackHandleScope<1> hs(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -07001123 Handle<mirror::CharArray> h_char_array(
1124 hs.NewHandle(shadow_frame->GetVRegReference(arg_offset + 3)->AsCharArray()));
Kenny Root57f91e82015-05-14 15:58:17 -07001125 DCHECK_LE(index, h_char_array->GetLength());
1126 DCHECK_LE(end - start, h_char_array->GetLength() - index);
Kenny Root1c9e61c2015-05-14 15:58:17 -07001127 string->GetChars(start, end, h_char_array, index);
1128}
1129
1130// This allows reading chars from the new style of String objects during compilation.
Andreas Gampe799681b2015-05-15 19:24:12 -07001131void UnstartedRuntime::UnstartedStringCharAt(
Mathieu Chartiere401d142015-04-22 13:56:20 -07001132 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Kenny Root1c9e61c2015-05-14 15:58:17 -07001133 jint index = shadow_frame->GetVReg(arg_offset + 1);
1134 mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
1135 if (string == nullptr) {
1136 AbortTransactionOrFail(self, "String.charAt with null object");
1137 return;
1138 }
1139 result->SetC(string->CharAt(index));
1140}
1141
Kenny Root57f91e82015-05-14 15:58:17 -07001142// This allows setting chars from the new style of String objects during compilation.
Andreas Gampe799681b2015-05-15 19:24:12 -07001143void UnstartedRuntime::UnstartedStringSetCharAt(
Mathieu Chartiere401d142015-04-22 13:56:20 -07001144 Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset) {
Kenny Root57f91e82015-05-14 15:58:17 -07001145 jint index = shadow_frame->GetVReg(arg_offset + 1);
1146 jchar c = shadow_frame->GetVReg(arg_offset + 2);
1147 mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
1148 if (string == nullptr) {
1149 AbortTransactionOrFail(self, "String.setCharAt with null object");
1150 return;
1151 }
1152 string->SetCharAt(index, c);
1153}
1154
Kenny Root1c9e61c2015-05-14 15:58:17 -07001155// This allows creating the new style of String objects during compilation.
Andreas Gampe799681b2015-05-15 19:24:12 -07001156void UnstartedRuntime::UnstartedStringFactoryNewStringFromChars(
Mathieu Chartiere401d142015-04-22 13:56:20 -07001157 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Kenny Root1c9e61c2015-05-14 15:58:17 -07001158 jint offset = shadow_frame->GetVReg(arg_offset);
1159 jint char_count = shadow_frame->GetVReg(arg_offset + 1);
1160 DCHECK_GE(char_count, 0);
1161 StackHandleScope<1> hs(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -07001162 Handle<mirror::CharArray> h_char_array(
1163 hs.NewHandle(shadow_frame->GetVRegReference(arg_offset + 2)->AsCharArray()));
Kenny Root1c9e61c2015-05-14 15:58:17 -07001164 Runtime* runtime = Runtime::Current();
1165 gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
1166 result->SetL(mirror::String::AllocFromCharArray<true>(self, char_count, h_char_array, offset, allocator));
1167}
1168
1169// This allows creating the new style of String objects during compilation.
Andreas Gampe799681b2015-05-15 19:24:12 -07001170void UnstartedRuntime::UnstartedStringFactoryNewStringFromString(
Mathieu Chartiere401d142015-04-22 13:56:20 -07001171 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Kenny Root57f91e82015-05-14 15:58:17 -07001172 mirror::String* to_copy = shadow_frame->GetVRegReference(arg_offset)->AsString();
1173 if (to_copy == nullptr) {
1174 AbortTransactionOrFail(self, "StringFactory.newStringFromString with null object");
1175 return;
1176 }
1177 StackHandleScope<1> hs(self);
1178 Handle<mirror::String> h_string(hs.NewHandle(to_copy));
1179 Runtime* runtime = Runtime::Current();
1180 gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
1181 result->SetL(mirror::String::AllocFromString<true>(self, h_string->GetLength(), h_string, 0,
1182 allocator));
1183}
1184
Andreas Gampe799681b2015-05-15 19:24:12 -07001185void UnstartedRuntime::UnstartedStringFastSubstring(
Mathieu Chartiere401d142015-04-22 13:56:20 -07001186 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Kenny Root1c9e61c2015-05-14 15:58:17 -07001187 jint start = shadow_frame->GetVReg(arg_offset + 1);
1188 jint length = shadow_frame->GetVReg(arg_offset + 2);
Kenny Root57f91e82015-05-14 15:58:17 -07001189 DCHECK_GE(start, 0);
Kenny Root1c9e61c2015-05-14 15:58:17 -07001190 DCHECK_GE(length, 0);
1191 StackHandleScope<1> hs(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -07001192 Handle<mirror::String> h_string(
1193 hs.NewHandle(shadow_frame->GetVRegReference(arg_offset)->AsString()));
Kenny Root57f91e82015-05-14 15:58:17 -07001194 DCHECK_LE(start, h_string->GetLength());
1195 DCHECK_LE(start + length, h_string->GetLength());
Kenny Root1c9e61c2015-05-14 15:58:17 -07001196 Runtime* runtime = Runtime::Current();
1197 gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
1198 result->SetL(mirror::String::AllocFromString<true>(self, length, h_string, start, allocator));
1199}
1200
Kenny Root57f91e82015-05-14 15:58:17 -07001201// This allows getting the char array for new style of String objects during compilation.
Andreas Gampe799681b2015-05-15 19:24:12 -07001202void UnstartedRuntime::UnstartedStringToCharArray(
Kenny Root57f91e82015-05-14 15:58:17 -07001203 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
Mathieu Chartier90443472015-07-16 20:32:27 -07001204 SHARED_REQUIRES(Locks::mutator_lock_) {
Kenny Root57f91e82015-05-14 15:58:17 -07001205 mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
1206 if (string == nullptr) {
1207 AbortTransactionOrFail(self, "String.charAt with null object");
1208 return;
1209 }
1210 result->SetL(string->ToCharArray(self));
1211}
1212
Andreas Gampebc4d2182016-02-22 10:03:12 -08001213// This allows statically initializing ConcurrentHashMap and SynchronousQueue.
1214void UnstartedRuntime::UnstartedReferenceGetReferent(
1215 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
1216 mirror::Reference* const ref = down_cast<mirror::Reference*>(
1217 shadow_frame->GetVRegReference(arg_offset));
1218 if (ref == nullptr) {
1219 AbortTransactionOrFail(self, "Reference.getReferent() with null object");
1220 return;
1221 }
1222 mirror::Object* const referent =
1223 Runtime::Current()->GetHeap()->GetReferenceProcessor()->GetReferent(self, ref);
1224 result->SetL(referent);
1225}
1226
1227// This allows statically initializing ConcurrentHashMap and SynchronousQueue. We use a somewhat
1228// conservative upper bound. We restrict the callers to SynchronousQueue and ConcurrentHashMap,
1229// where we can predict the behavior (somewhat).
1230// Note: this is required (instead of lazy initialization) as these classes are used in the static
1231// initialization of other classes, so will *use* the value.
1232void UnstartedRuntime::UnstartedRuntimeAvailableProcessors(
1233 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset ATTRIBUTE_UNUSED) {
1234 std::string caller(PrettyMethod(shadow_frame->GetLink()->GetMethod()));
1235 if (caller == "void java.util.concurrent.SynchronousQueue.<clinit>()") {
1236 // SynchronousQueue really only separates between single- and multiprocessor case. Return
1237 // 8 as a conservative upper approximation.
1238 result->SetI(8);
1239 } else if (caller == "void java.util.concurrent.ConcurrentHashMap.<clinit>()") {
1240 // ConcurrentHashMap uses it for striding. 8 still seems an OK general value, as it's likely
1241 // a good upper bound.
1242 // TODO: Consider resetting in the zygote?
1243 result->SetI(8);
1244 } else {
1245 // Not supported.
1246 AbortTransactionOrFail(self, "Accessing availableProcessors not allowed");
1247 }
1248}
1249
1250// This allows accessing ConcurrentHashMap/SynchronousQueue.
1251
1252void UnstartedRuntime::UnstartedUnsafeCompareAndSwapLong(
1253 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
1254 // Argument 0 is the Unsafe instance, skip.
1255 mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset + 1);
1256 if (obj == nullptr) {
1257 AbortTransactionOrFail(self, "Cannot access null object, retry at runtime.");
1258 return;
1259 }
1260 int64_t offset = shadow_frame->GetVRegLong(arg_offset + 2);
1261 int64_t expectedValue = shadow_frame->GetVRegLong(arg_offset + 4);
1262 int64_t newValue = shadow_frame->GetVRegLong(arg_offset + 6);
1263
1264 // Must use non transactional mode.
1265 if (kUseReadBarrier) {
1266 // Need to make sure the reference stored in the field is a to-space one before attempting the
1267 // CAS or the CAS could fail incorrectly.
1268 mirror::HeapReference<mirror::Object>* field_addr =
1269 reinterpret_cast<mirror::HeapReference<mirror::Object>*>(
1270 reinterpret_cast<uint8_t*>(obj) + static_cast<size_t>(offset));
1271 ReadBarrier::Barrier<mirror::Object, kWithReadBarrier, /*kAlwaysUpdateField*/true>(
1272 obj,
1273 MemberOffset(offset),
1274 field_addr);
1275 }
1276 bool success;
1277 // Check whether we're in a transaction, call accordingly.
1278 if (Runtime::Current()->IsActiveTransaction()) {
1279 success = obj->CasFieldStrongSequentiallyConsistent64<true>(MemberOffset(offset),
1280 expectedValue,
1281 newValue);
1282 } else {
1283 success = obj->CasFieldStrongSequentiallyConsistent64<false>(MemberOffset(offset),
1284 expectedValue,
1285 newValue);
1286 }
1287 result->SetZ(success ? 1 : 0);
1288}
1289
1290void UnstartedRuntime::UnstartedUnsafeCompareAndSwapObject(
1291 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
1292 // Argument 0 is the Unsafe instance, skip.
1293 mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset + 1);
1294 if (obj == nullptr) {
1295 AbortTransactionOrFail(self, "Cannot access null object, retry at runtime.");
1296 return;
1297 }
1298 int64_t offset = shadow_frame->GetVRegLong(arg_offset + 2);
1299 mirror::Object* expected_value = shadow_frame->GetVRegReference(arg_offset + 4);
1300 mirror::Object* newValue = shadow_frame->GetVRegReference(arg_offset + 5);
1301
1302 // Must use non transactional mode.
1303 if (kUseReadBarrier) {
1304 // Need to make sure the reference stored in the field is a to-space one before attempting the
1305 // CAS or the CAS could fail incorrectly.
1306 mirror::HeapReference<mirror::Object>* field_addr =
1307 reinterpret_cast<mirror::HeapReference<mirror::Object>*>(
1308 reinterpret_cast<uint8_t*>(obj) + static_cast<size_t>(offset));
1309 ReadBarrier::Barrier<mirror::Object, kWithReadBarrier, /*kAlwaysUpdateField*/true>(
1310 obj,
1311 MemberOffset(offset),
1312 field_addr);
1313 }
1314 bool success;
1315 // Check whether we're in a transaction, call accordingly.
1316 if (Runtime::Current()->IsActiveTransaction()) {
1317 success = obj->CasFieldStrongSequentiallyConsistentObject<true>(MemberOffset(offset),
1318 expected_value,
1319 newValue);
1320 } else {
1321 success = obj->CasFieldStrongSequentiallyConsistentObject<false>(MemberOffset(offset),
1322 expected_value,
1323 newValue);
1324 }
1325 result->SetZ(success ? 1 : 0);
1326}
1327
1328void UnstartedRuntime::UnstartedUnsafeGetObjectVolatile(
1329 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
1330 SHARED_REQUIRES(Locks::mutator_lock_) {
1331 // Argument 0 is the Unsafe instance, skip.
1332 mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset + 1);
1333 if (obj == nullptr) {
1334 AbortTransactionOrFail(self, "Cannot access null object, retry at runtime.");
1335 return;
1336 }
1337 int64_t offset = shadow_frame->GetVRegLong(arg_offset + 2);
1338 mirror::Object* value = obj->GetFieldObjectVolatile<mirror::Object>(MemberOffset(offset));
1339 result->SetL(value);
1340}
1341
Andreas Gampe8a18fde2016-04-05 21:12:51 -07001342void UnstartedRuntime::UnstartedUnsafePutObjectVolatile(
1343 Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset)
1344 SHARED_REQUIRES(Locks::mutator_lock_) {
1345 // Argument 0 is the Unsafe instance, skip.
1346 mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset + 1);
1347 if (obj == nullptr) {
1348 AbortTransactionOrFail(self, "Cannot access null object, retry at runtime.");
1349 return;
1350 }
1351 int64_t offset = shadow_frame->GetVRegLong(arg_offset + 2);
1352 mirror::Object* value = shadow_frame->GetVRegReference(arg_offset + 4);
1353 if (Runtime::Current()->IsActiveTransaction()) {
1354 obj->SetFieldObjectVolatile<true>(MemberOffset(offset), value);
1355 } else {
1356 obj->SetFieldObjectVolatile<false>(MemberOffset(offset), value);
1357 }
1358}
1359
Andreas Gampebc4d2182016-02-22 10:03:12 -08001360void UnstartedRuntime::UnstartedUnsafePutOrderedObject(
1361 Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset)
1362 SHARED_REQUIRES(Locks::mutator_lock_) {
1363 // Argument 0 is the Unsafe instance, skip.
1364 mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset + 1);
1365 if (obj == nullptr) {
1366 AbortTransactionOrFail(self, "Cannot access null object, retry at runtime.");
1367 return;
1368 }
1369 int64_t offset = shadow_frame->GetVRegLong(arg_offset + 2);
1370 mirror::Object* newValue = shadow_frame->GetVRegReference(arg_offset + 4);
1371 QuasiAtomic::ThreadFenceRelease();
1372 if (Runtime::Current()->IsActiveTransaction()) {
1373 obj->SetFieldObject<true>(MemberOffset(offset), newValue);
1374 } else {
1375 obj->SetFieldObject<false>(MemberOffset(offset), newValue);
1376 }
1377}
1378
Andreas Gampe13fc1be2016-04-05 20:14:30 -07001379// A cutout for Integer.parseInt(String). Note: this code is conservative and will bail instead
1380// of correctly handling the corner cases.
1381void UnstartedRuntime::UnstartedIntegerParseInt(
1382 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
1383 SHARED_REQUIRES(Locks::mutator_lock_) {
1384 mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset);
1385 if (obj == nullptr) {
1386 AbortTransactionOrFail(self, "Cannot parse null string, retry at runtime.");
1387 return;
1388 }
1389
1390 std::string string_value = obj->AsString()->ToModifiedUtf8();
1391 if (string_value.empty()) {
1392 AbortTransactionOrFail(self, "Cannot parse empty string, retry at runtime.");
1393 return;
1394 }
1395
1396 const char* c_str = string_value.c_str();
1397 char *end;
1398 // Can we set errno to 0? Is this always a variable, and not a macro?
1399 // Worst case, we'll incorrectly fail a transaction. Seems OK.
1400 int64_t l = strtol(c_str, &end, 10);
1401
1402 if ((errno == ERANGE && l == LONG_MAX) || l > std::numeric_limits<int32_t>::max() ||
1403 (errno == ERANGE && l == LONG_MIN) || l < std::numeric_limits<int32_t>::min()) {
1404 AbortTransactionOrFail(self, "Cannot parse string %s, retry at runtime.", c_str);
1405 return;
1406 }
1407 if (l == 0) {
1408 // Check whether the string wasn't exactly zero.
1409 if (string_value != "0") {
1410 AbortTransactionOrFail(self, "Cannot parse string %s, retry at runtime.", c_str);
1411 return;
1412 }
1413 } else if (*end != '\0') {
1414 AbortTransactionOrFail(self, "Cannot parse string %s, retry at runtime.", c_str);
1415 return;
1416 }
1417
1418 result->SetI(static_cast<int32_t>(l));
1419}
1420
1421// A cutout for Long.parseLong.
1422//
1423// Note: for now use code equivalent to Integer.parseInt, as the full range may not be supported
1424// well.
1425void UnstartedRuntime::UnstartedLongParseLong(
1426 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
1427 SHARED_REQUIRES(Locks::mutator_lock_) {
1428 mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset);
1429 if (obj == nullptr) {
1430 AbortTransactionOrFail(self, "Cannot parse null string, retry at runtime.");
1431 return;
1432 }
1433
1434 std::string string_value = obj->AsString()->ToModifiedUtf8();
1435 if (string_value.empty()) {
1436 AbortTransactionOrFail(self, "Cannot parse empty string, retry at runtime.");
1437 return;
1438 }
1439
1440 const char* c_str = string_value.c_str();
1441 char *end;
1442 // Can we set errno to 0? Is this always a variable, and not a macro?
1443 // Worst case, we'll incorrectly fail a transaction. Seems OK.
1444 int64_t l = strtol(c_str, &end, 10);
1445
1446 // Note: comparing against int32_t min/max is intentional here.
1447 if ((errno == ERANGE && l == LONG_MAX) || l > std::numeric_limits<int32_t>::max() ||
1448 (errno == ERANGE && l == LONG_MIN) || l < std::numeric_limits<int32_t>::min()) {
1449 AbortTransactionOrFail(self, "Cannot parse string %s, retry at runtime.", c_str);
1450 return;
1451 }
1452 if (l == 0) {
1453 // Check whether the string wasn't exactly zero.
1454 if (string_value != "0") {
1455 AbortTransactionOrFail(self, "Cannot parse string %s, retry at runtime.", c_str);
1456 return;
1457 }
1458 } else if (*end != '\0') {
1459 AbortTransactionOrFail(self, "Cannot parse string %s, retry at runtime.", c_str);
1460 return;
1461 }
1462
1463 result->SetJ(l);
1464}
1465
Andreas Gampebc4d2182016-02-22 10:03:12 -08001466
Mathieu Chartiere401d142015-04-22 13:56:20 -07001467void UnstartedRuntime::UnstartedJNIVMRuntimeNewUnpaddedArray(
1468 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
1469 uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001470 int32_t length = args[1];
1471 DCHECK_GE(length, 0);
1472 mirror::Class* element_class = reinterpret_cast<mirror::Object*>(args[0])->AsClass();
1473 Runtime* runtime = Runtime::Current();
1474 mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(self, &element_class);
1475 DCHECK(array_class != nullptr);
1476 gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
1477 result->SetL(mirror::Array::Alloc<true, true>(self, array_class, length,
1478 array_class->GetComponentSizeShift(), allocator));
1479}
1480
Mathieu Chartiere401d142015-04-22 13:56:20 -07001481void UnstartedRuntime::UnstartedJNIVMStackGetCallingClassLoader(
1482 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1483 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001484 result->SetL(nullptr);
1485}
1486
Mathieu Chartiere401d142015-04-22 13:56:20 -07001487void UnstartedRuntime::UnstartedJNIVMStackGetStackClass2(
1488 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
1489 uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001490 NthCallerVisitor visitor(self, 3);
1491 visitor.WalkStack();
1492 if (visitor.caller != nullptr) {
1493 result->SetL(visitor.caller->GetDeclaringClass());
1494 }
1495}
1496
Mathieu Chartiere401d142015-04-22 13:56:20 -07001497void UnstartedRuntime::UnstartedJNIMathLog(
1498 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1499 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001500 JValue value;
1501 value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
1502 result->SetD(log(value.GetD()));
1503}
1504
Mathieu Chartiere401d142015-04-22 13:56:20 -07001505void UnstartedRuntime::UnstartedJNIMathExp(
1506 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1507 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001508 JValue value;
1509 value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
1510 result->SetD(exp(value.GetD()));
1511}
1512
Andreas Gampebc4d2182016-02-22 10:03:12 -08001513void UnstartedRuntime::UnstartedJNIAtomicLongVMSupportsCS8(
1514 Thread* self ATTRIBUTE_UNUSED,
1515 ArtMethod* method ATTRIBUTE_UNUSED,
1516 mirror::Object* receiver ATTRIBUTE_UNUSED,
1517 uint32_t* args ATTRIBUTE_UNUSED,
1518 JValue* result) {
1519 result->SetZ(QuasiAtomic::LongAtomicsUseMutexes(Runtime::Current()->GetInstructionSet())
1520 ? 0
1521 : 1);
1522}
1523
Mathieu Chartiere401d142015-04-22 13:56:20 -07001524void UnstartedRuntime::UnstartedJNIClassGetNameNative(
1525 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver,
1526 uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001527 StackHandleScope<1> hs(self);
1528 result->SetL(mirror::Class::ComputeName(hs.NewHandle(receiver->AsClass())));
1529}
1530
Andreas Gampebc4d2182016-02-22 10:03:12 -08001531void UnstartedRuntime::UnstartedJNIDoubleLongBitsToDouble(
1532 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1533 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
1534 uint64_t long_input = args[0] | (static_cast<uint64_t>(args[1]) << 32);
1535 result->SetD(bit_cast<double>(long_input));
1536}
1537
Mathieu Chartiere401d142015-04-22 13:56:20 -07001538void UnstartedRuntime::UnstartedJNIFloatFloatToRawIntBits(
1539 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1540 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001541 result->SetI(args[0]);
1542}
1543
Mathieu Chartiere401d142015-04-22 13:56:20 -07001544void UnstartedRuntime::UnstartedJNIFloatIntBitsToFloat(
1545 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1546 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001547 result->SetI(args[0]);
1548}
1549
Mathieu Chartiere401d142015-04-22 13:56:20 -07001550void UnstartedRuntime::UnstartedJNIObjectInternalClone(
1551 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver,
1552 uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001553 result->SetL(receiver->Clone(self));
1554}
1555
Mathieu Chartiere401d142015-04-22 13:56:20 -07001556void UnstartedRuntime::UnstartedJNIObjectNotifyAll(
1557 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver,
1558 uint32_t* args ATTRIBUTE_UNUSED, JValue* result ATTRIBUTE_UNUSED) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001559 receiver->NotifyAll(self);
1560}
1561
Mathieu Chartiere401d142015-04-22 13:56:20 -07001562void UnstartedRuntime::UnstartedJNIStringCompareTo(
1563 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver, uint32_t* args,
1564 JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001565 mirror::String* rhs = reinterpret_cast<mirror::Object*>(args[0])->AsString();
1566 if (rhs == nullptr) {
Andreas Gampe068b0c02015-03-11 12:44:47 -07001567 AbortTransactionOrFail(self, "String.compareTo with null object");
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001568 }
1569 result->SetI(receiver->AsString()->CompareTo(rhs));
1570}
1571
Mathieu Chartiere401d142015-04-22 13:56:20 -07001572void UnstartedRuntime::UnstartedJNIStringIntern(
1573 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver,
1574 uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001575 result->SetL(receiver->AsString()->Intern());
1576}
1577
Mathieu Chartiere401d142015-04-22 13:56:20 -07001578void UnstartedRuntime::UnstartedJNIStringFastIndexOf(
1579 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver,
1580 uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001581 result->SetI(receiver->AsString()->FastIndexOf(args[0], args[1]));
1582}
1583
Mathieu Chartiere401d142015-04-22 13:56:20 -07001584void UnstartedRuntime::UnstartedJNIArrayCreateMultiArray(
1585 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
1586 uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001587 StackHandleScope<2> hs(self);
1588 auto h_class(hs.NewHandle(reinterpret_cast<mirror::Class*>(args[0])->AsClass()));
1589 auto h_dimensions(hs.NewHandle(reinterpret_cast<mirror::IntArray*>(args[1])->AsIntArray()));
1590 result->SetL(mirror::Array::CreateMultiArray(self, h_class, h_dimensions));
1591}
1592
Mathieu Chartiere401d142015-04-22 13:56:20 -07001593void UnstartedRuntime::UnstartedJNIArrayCreateObjectArray(
1594 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
1595 uint32_t* args, JValue* result) {
Andreas Gampee598e042015-04-10 14:57:10 -07001596 int32_t length = static_cast<int32_t>(args[1]);
1597 if (length < 0) {
1598 ThrowNegativeArraySizeException(length);
1599 return;
1600 }
1601 mirror::Class* element_class = reinterpret_cast<mirror::Class*>(args[0])->AsClass();
1602 Runtime* runtime = Runtime::Current();
1603 ClassLinker* class_linker = runtime->GetClassLinker();
1604 mirror::Class* array_class = class_linker->FindArrayClass(self, &element_class);
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001605 if (UNLIKELY(array_class == nullptr)) {
Andreas Gampee598e042015-04-10 14:57:10 -07001606 CHECK(self->IsExceptionPending());
1607 return;
1608 }
1609 DCHECK(array_class->IsObjectArrayClass());
1610 mirror::Array* new_array = mirror::ObjectArray<mirror::Object*>::Alloc(
1611 self, array_class, length, runtime->GetHeap()->GetCurrentAllocator());
1612 result->SetL(new_array);
1613}
1614
Mathieu Chartiere401d142015-04-22 13:56:20 -07001615void UnstartedRuntime::UnstartedJNIThrowableNativeFillInStackTrace(
1616 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
1617 uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001618 ScopedObjectAccessUnchecked soa(self);
1619 if (Runtime::Current()->IsActiveTransaction()) {
1620 result->SetL(soa.Decode<mirror::Object*>(self->CreateInternalStackTrace<true>(soa)));
1621 } else {
1622 result->SetL(soa.Decode<mirror::Object*>(self->CreateInternalStackTrace<false>(soa)));
1623 }
1624}
1625
Mathieu Chartiere401d142015-04-22 13:56:20 -07001626void UnstartedRuntime::UnstartedJNISystemIdentityHashCode(
1627 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1628 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001629 mirror::Object* obj = reinterpret_cast<mirror::Object*>(args[0]);
1630 result->SetI((obj != nullptr) ? obj->IdentityHashCode() : 0);
1631}
1632
Mathieu Chartiere401d142015-04-22 13:56:20 -07001633void UnstartedRuntime::UnstartedJNIByteOrderIsLittleEndian(
1634 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1635 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001636 result->SetZ(JNI_TRUE);
1637}
1638
Mathieu Chartiere401d142015-04-22 13:56:20 -07001639void UnstartedRuntime::UnstartedJNIUnsafeCompareAndSwapInt(
1640 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1641 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001642 mirror::Object* obj = reinterpret_cast<mirror::Object*>(args[0]);
1643 jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1];
1644 jint expectedValue = args[3];
1645 jint newValue = args[4];
1646 bool success;
1647 if (Runtime::Current()->IsActiveTransaction()) {
1648 success = obj->CasFieldStrongSequentiallyConsistent32<true>(MemberOffset(offset),
1649 expectedValue, newValue);
1650 } else {
1651 success = obj->CasFieldStrongSequentiallyConsistent32<false>(MemberOffset(offset),
1652 expectedValue, newValue);
1653 }
1654 result->SetZ(success ? JNI_TRUE : JNI_FALSE);
1655}
1656
Narayan Kamath34a316f2016-03-30 13:11:18 +01001657void UnstartedRuntime::UnstartedJNIUnsafeGetIntVolatile(
1658 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
1659 uint32_t* args, JValue* result) {
1660 mirror::Object* obj = reinterpret_cast<mirror::Object*>(args[0]);
1661 if (obj == nullptr) {
1662 AbortTransactionOrFail(self, "Cannot access null object, retry at runtime.");
1663 return;
1664 }
1665
1666 jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1];
1667 result->SetI(obj->GetField32Volatile(MemberOffset(offset)));
1668}
1669
Mathieu Chartiere401d142015-04-22 13:56:20 -07001670void UnstartedRuntime::UnstartedJNIUnsafePutObject(
1671 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1672 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result ATTRIBUTE_UNUSED) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001673 mirror::Object* obj = reinterpret_cast<mirror::Object*>(args[0]);
1674 jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1];
1675 mirror::Object* newValue = reinterpret_cast<mirror::Object*>(args[3]);
1676 if (Runtime::Current()->IsActiveTransaction()) {
1677 obj->SetFieldObject<true>(MemberOffset(offset), newValue);
1678 } else {
1679 obj->SetFieldObject<false>(MemberOffset(offset), newValue);
1680 }
1681}
1682
Andreas Gampe799681b2015-05-15 19:24:12 -07001683void UnstartedRuntime::UnstartedJNIUnsafeGetArrayBaseOffsetForComponentType(
Mathieu Chartiere401d142015-04-22 13:56:20 -07001684 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1685 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001686 mirror::Class* component = reinterpret_cast<mirror::Object*>(args[0])->AsClass();
1687 Primitive::Type primitive_type = component->GetPrimitiveType();
1688 result->SetI(mirror::Array::DataOffset(Primitive::ComponentSize(primitive_type)).Int32Value());
1689}
1690
Andreas Gampe799681b2015-05-15 19:24:12 -07001691void UnstartedRuntime::UnstartedJNIUnsafeGetArrayIndexScaleForComponentType(
Mathieu Chartiere401d142015-04-22 13:56:20 -07001692 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1693 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001694 mirror::Class* component = reinterpret_cast<mirror::Object*>(args[0])->AsClass();
1695 Primitive::Type primitive_type = component->GetPrimitiveType();
1696 result->SetI(Primitive::ComponentSize(primitive_type));
1697}
1698
Andreas Gampedd9d0552015-03-09 12:57:41 -07001699typedef void (*InvokeHandler)(Thread* self, ShadowFrame* shadow_frame, JValue* result,
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001700 size_t arg_size);
1701
Mathieu Chartiere401d142015-04-22 13:56:20 -07001702typedef void (*JNIHandler)(Thread* self, ArtMethod* method, mirror::Object* receiver,
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001703 uint32_t* args, JValue* result);
1704
1705static bool tables_initialized_ = false;
1706static std::unordered_map<std::string, InvokeHandler> invoke_handlers_;
1707static std::unordered_map<std::string, JNIHandler> jni_handlers_;
1708
Andreas Gampe799681b2015-05-15 19:24:12 -07001709void UnstartedRuntime::InitializeInvokeHandlers() {
1710#define UNSTARTED_DIRECT(ShortName, Sig) \
1711 invoke_handlers_.insert(std::make_pair(Sig, & UnstartedRuntime::Unstarted ## ShortName));
1712#include "unstarted_runtime_list.h"
1713 UNSTARTED_RUNTIME_DIRECT_LIST(UNSTARTED_DIRECT)
1714#undef UNSTARTED_RUNTIME_DIRECT_LIST
1715#undef UNSTARTED_RUNTIME_JNI_LIST
1716#undef UNSTARTED_DIRECT
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001717}
1718
Andreas Gampe799681b2015-05-15 19:24:12 -07001719void UnstartedRuntime::InitializeJNIHandlers() {
1720#define UNSTARTED_JNI(ShortName, Sig) \
1721 jni_handlers_.insert(std::make_pair(Sig, & UnstartedRuntime::UnstartedJNI ## ShortName));
1722#include "unstarted_runtime_list.h"
1723 UNSTARTED_RUNTIME_JNI_LIST(UNSTARTED_JNI)
1724#undef UNSTARTED_RUNTIME_DIRECT_LIST
1725#undef UNSTARTED_RUNTIME_JNI_LIST
1726#undef UNSTARTED_JNI
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001727}
1728
Andreas Gampe799681b2015-05-15 19:24:12 -07001729void UnstartedRuntime::Initialize() {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001730 CHECK(!tables_initialized_);
1731
Andreas Gampe799681b2015-05-15 19:24:12 -07001732 InitializeInvokeHandlers();
1733 InitializeJNIHandlers();
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001734
1735 tables_initialized_ = true;
1736}
1737
Andreas Gampe799681b2015-05-15 19:24:12 -07001738void UnstartedRuntime::Invoke(Thread* self, const DexFile::CodeItem* code_item,
1739 ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001740 // In a runtime that's not started we intercept certain methods to avoid complicated dependency
1741 // problems in core libraries.
1742 CHECK(tables_initialized_);
1743
1744 std::string name(PrettyMethod(shadow_frame->GetMethod()));
1745 const auto& iter = invoke_handlers_.find(name);
1746 if (iter != invoke_handlers_.end()) {
Kenny Root57f91e82015-05-14 15:58:17 -07001747 // Clear out the result in case it's not zeroed out.
1748 result->SetL(0);
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001749 (*iter->second)(self, shadow_frame, result, arg_offset);
1750 } else {
1751 // Not special, continue with regular interpreter execution.
Andreas Gampe3cfa4d02015-10-06 17:04:01 -07001752 ArtInterpreterToInterpreterBridge(self, code_item, shadow_frame, result);
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001753 }
1754}
1755
1756// Hand select a number of methods to be run in a not yet started runtime without using JNI.
Mathieu Chartiere401d142015-04-22 13:56:20 -07001757void UnstartedRuntime::Jni(Thread* self, ArtMethod* method, mirror::Object* receiver,
Andreas Gampe799681b2015-05-15 19:24:12 -07001758 uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001759 std::string name(PrettyMethod(method));
1760 const auto& iter = jni_handlers_.find(name);
1761 if (iter != jni_handlers_.end()) {
Kenny Root57f91e82015-05-14 15:58:17 -07001762 // Clear out the result in case it's not zeroed out.
1763 result->SetL(0);
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001764 (*iter->second)(self, method, receiver, args, result);
1765 } else if (Runtime::Current()->IsActiveTransaction()) {
Sebastien Hertz45b15972015-04-03 16:07:05 +02001766 AbortTransactionF(self, "Attempt to invoke native method in non-started runtime: %s",
1767 name.c_str());
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001768 } else {
1769 LOG(FATAL) << "Calling native method " << PrettyMethod(method) << " in an unstarted "
1770 "non-transactional runtime";
1771 }
1772}
1773
1774} // namespace interpreter
1775} // namespace art