blob: 5de0863d152d0a70e026601606041a1abdcf6c66 [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
Kenny Root1c9e61c2015-05-14 15:58:17 -07001003// This allows reading the new style of String objects during compilation.
Andreas Gampe799681b2015-05-15 19:24:12 -07001004void UnstartedRuntime::UnstartedStringGetCharsNoCheck(
Mathieu Chartiere401d142015-04-22 13:56:20 -07001005 Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset) {
Kenny Root1c9e61c2015-05-14 15:58:17 -07001006 jint start = shadow_frame->GetVReg(arg_offset + 1);
1007 jint end = shadow_frame->GetVReg(arg_offset + 2);
1008 jint index = shadow_frame->GetVReg(arg_offset + 4);
1009 mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
1010 if (string == nullptr) {
1011 AbortTransactionOrFail(self, "String.getCharsNoCheck with null object");
1012 return;
1013 }
Kenny Root57f91e82015-05-14 15:58:17 -07001014 DCHECK_GE(start, 0);
1015 DCHECK_GE(end, string->GetLength());
Kenny Root1c9e61c2015-05-14 15:58:17 -07001016 StackHandleScope<1> hs(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -07001017 Handle<mirror::CharArray> h_char_array(
1018 hs.NewHandle(shadow_frame->GetVRegReference(arg_offset + 3)->AsCharArray()));
Kenny Root57f91e82015-05-14 15:58:17 -07001019 DCHECK_LE(index, h_char_array->GetLength());
1020 DCHECK_LE(end - start, h_char_array->GetLength() - index);
Kenny Root1c9e61c2015-05-14 15:58:17 -07001021 string->GetChars(start, end, h_char_array, index);
1022}
1023
1024// This allows reading chars from the new style of String objects during compilation.
Andreas Gampe799681b2015-05-15 19:24:12 -07001025void UnstartedRuntime::UnstartedStringCharAt(
Mathieu Chartiere401d142015-04-22 13:56:20 -07001026 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Kenny Root1c9e61c2015-05-14 15:58:17 -07001027 jint index = shadow_frame->GetVReg(arg_offset + 1);
1028 mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
1029 if (string == nullptr) {
1030 AbortTransactionOrFail(self, "String.charAt with null object");
1031 return;
1032 }
1033 result->SetC(string->CharAt(index));
1034}
1035
Kenny Root57f91e82015-05-14 15:58:17 -07001036// This allows setting chars from the new style of String objects during compilation.
Andreas Gampe799681b2015-05-15 19:24:12 -07001037void UnstartedRuntime::UnstartedStringSetCharAt(
Mathieu Chartiere401d142015-04-22 13:56:20 -07001038 Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset) {
Kenny Root57f91e82015-05-14 15:58:17 -07001039 jint index = shadow_frame->GetVReg(arg_offset + 1);
1040 jchar c = shadow_frame->GetVReg(arg_offset + 2);
1041 mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
1042 if (string == nullptr) {
1043 AbortTransactionOrFail(self, "String.setCharAt with null object");
1044 return;
1045 }
1046 string->SetCharAt(index, c);
1047}
1048
Kenny Root1c9e61c2015-05-14 15:58:17 -07001049// This allows creating the new style of String objects during compilation.
Andreas Gampe799681b2015-05-15 19:24:12 -07001050void UnstartedRuntime::UnstartedStringFactoryNewStringFromChars(
Mathieu Chartiere401d142015-04-22 13:56:20 -07001051 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Kenny Root1c9e61c2015-05-14 15:58:17 -07001052 jint offset = shadow_frame->GetVReg(arg_offset);
1053 jint char_count = shadow_frame->GetVReg(arg_offset + 1);
1054 DCHECK_GE(char_count, 0);
1055 StackHandleScope<1> hs(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -07001056 Handle<mirror::CharArray> h_char_array(
1057 hs.NewHandle(shadow_frame->GetVRegReference(arg_offset + 2)->AsCharArray()));
Kenny Root1c9e61c2015-05-14 15:58:17 -07001058 Runtime* runtime = Runtime::Current();
1059 gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
1060 result->SetL(mirror::String::AllocFromCharArray<true>(self, char_count, h_char_array, offset, allocator));
1061}
1062
1063// This allows creating the new style of String objects during compilation.
Andreas Gampe799681b2015-05-15 19:24:12 -07001064void UnstartedRuntime::UnstartedStringFactoryNewStringFromString(
Mathieu Chartiere401d142015-04-22 13:56:20 -07001065 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Kenny Root57f91e82015-05-14 15:58:17 -07001066 mirror::String* to_copy = shadow_frame->GetVRegReference(arg_offset)->AsString();
1067 if (to_copy == nullptr) {
1068 AbortTransactionOrFail(self, "StringFactory.newStringFromString with null object");
1069 return;
1070 }
1071 StackHandleScope<1> hs(self);
1072 Handle<mirror::String> h_string(hs.NewHandle(to_copy));
1073 Runtime* runtime = Runtime::Current();
1074 gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
1075 result->SetL(mirror::String::AllocFromString<true>(self, h_string->GetLength(), h_string, 0,
1076 allocator));
1077}
1078
Andreas Gampe799681b2015-05-15 19:24:12 -07001079void UnstartedRuntime::UnstartedStringFastSubstring(
Mathieu Chartiere401d142015-04-22 13:56:20 -07001080 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Kenny Root1c9e61c2015-05-14 15:58:17 -07001081 jint start = shadow_frame->GetVReg(arg_offset + 1);
1082 jint length = shadow_frame->GetVReg(arg_offset + 2);
Kenny Root57f91e82015-05-14 15:58:17 -07001083 DCHECK_GE(start, 0);
Kenny Root1c9e61c2015-05-14 15:58:17 -07001084 DCHECK_GE(length, 0);
1085 StackHandleScope<1> hs(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -07001086 Handle<mirror::String> h_string(
1087 hs.NewHandle(shadow_frame->GetVRegReference(arg_offset)->AsString()));
Kenny Root57f91e82015-05-14 15:58:17 -07001088 DCHECK_LE(start, h_string->GetLength());
1089 DCHECK_LE(start + length, h_string->GetLength());
Kenny Root1c9e61c2015-05-14 15:58:17 -07001090 Runtime* runtime = Runtime::Current();
1091 gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
1092 result->SetL(mirror::String::AllocFromString<true>(self, length, h_string, start, allocator));
1093}
1094
Kenny Root57f91e82015-05-14 15:58:17 -07001095// This allows getting the char array for new style of String objects during compilation.
Andreas Gampe799681b2015-05-15 19:24:12 -07001096void UnstartedRuntime::UnstartedStringToCharArray(
Kenny Root57f91e82015-05-14 15:58:17 -07001097 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
Mathieu Chartier90443472015-07-16 20:32:27 -07001098 SHARED_REQUIRES(Locks::mutator_lock_) {
Kenny Root57f91e82015-05-14 15:58:17 -07001099 mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
1100 if (string == nullptr) {
1101 AbortTransactionOrFail(self, "String.charAt with null object");
1102 return;
1103 }
1104 result->SetL(string->ToCharArray(self));
1105}
1106
Andreas Gampebc4d2182016-02-22 10:03:12 -08001107// This allows statically initializing ConcurrentHashMap and SynchronousQueue.
1108void UnstartedRuntime::UnstartedReferenceGetReferent(
1109 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
1110 mirror::Reference* const ref = down_cast<mirror::Reference*>(
1111 shadow_frame->GetVRegReference(arg_offset));
1112 if (ref == nullptr) {
1113 AbortTransactionOrFail(self, "Reference.getReferent() with null object");
1114 return;
1115 }
1116 mirror::Object* const referent =
1117 Runtime::Current()->GetHeap()->GetReferenceProcessor()->GetReferent(self, ref);
1118 result->SetL(referent);
1119}
1120
1121// This allows statically initializing ConcurrentHashMap and SynchronousQueue. We use a somewhat
1122// conservative upper bound. We restrict the callers to SynchronousQueue and ConcurrentHashMap,
1123// where we can predict the behavior (somewhat).
1124// Note: this is required (instead of lazy initialization) as these classes are used in the static
1125// initialization of other classes, so will *use* the value.
1126void UnstartedRuntime::UnstartedRuntimeAvailableProcessors(
1127 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset ATTRIBUTE_UNUSED) {
1128 std::string caller(PrettyMethod(shadow_frame->GetLink()->GetMethod()));
1129 if (caller == "void java.util.concurrent.SynchronousQueue.<clinit>()") {
1130 // SynchronousQueue really only separates between single- and multiprocessor case. Return
1131 // 8 as a conservative upper approximation.
1132 result->SetI(8);
1133 } else if (caller == "void java.util.concurrent.ConcurrentHashMap.<clinit>()") {
1134 // ConcurrentHashMap uses it for striding. 8 still seems an OK general value, as it's likely
1135 // a good upper bound.
1136 // TODO: Consider resetting in the zygote?
1137 result->SetI(8);
1138 } else {
1139 // Not supported.
1140 AbortTransactionOrFail(self, "Accessing availableProcessors not allowed");
1141 }
1142}
1143
1144// This allows accessing ConcurrentHashMap/SynchronousQueue.
1145
1146void UnstartedRuntime::UnstartedUnsafeCompareAndSwapLong(
1147 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
1148 // Argument 0 is the Unsafe instance, skip.
1149 mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset + 1);
1150 if (obj == nullptr) {
1151 AbortTransactionOrFail(self, "Cannot access null object, retry at runtime.");
1152 return;
1153 }
1154 int64_t offset = shadow_frame->GetVRegLong(arg_offset + 2);
1155 int64_t expectedValue = shadow_frame->GetVRegLong(arg_offset + 4);
1156 int64_t newValue = shadow_frame->GetVRegLong(arg_offset + 6);
1157
1158 // Must use non transactional mode.
1159 if (kUseReadBarrier) {
1160 // Need to make sure the reference stored in the field is a to-space one before attempting the
1161 // CAS or the CAS could fail incorrectly.
1162 mirror::HeapReference<mirror::Object>* field_addr =
1163 reinterpret_cast<mirror::HeapReference<mirror::Object>*>(
1164 reinterpret_cast<uint8_t*>(obj) + static_cast<size_t>(offset));
1165 ReadBarrier::Barrier<mirror::Object, kWithReadBarrier, /*kAlwaysUpdateField*/true>(
1166 obj,
1167 MemberOffset(offset),
1168 field_addr);
1169 }
1170 bool success;
1171 // Check whether we're in a transaction, call accordingly.
1172 if (Runtime::Current()->IsActiveTransaction()) {
1173 success = obj->CasFieldStrongSequentiallyConsistent64<true>(MemberOffset(offset),
1174 expectedValue,
1175 newValue);
1176 } else {
1177 success = obj->CasFieldStrongSequentiallyConsistent64<false>(MemberOffset(offset),
1178 expectedValue,
1179 newValue);
1180 }
1181 result->SetZ(success ? 1 : 0);
1182}
1183
1184void UnstartedRuntime::UnstartedUnsafeCompareAndSwapObject(
1185 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
1186 // Argument 0 is the Unsafe instance, skip.
1187 mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset + 1);
1188 if (obj == nullptr) {
1189 AbortTransactionOrFail(self, "Cannot access null object, retry at runtime.");
1190 return;
1191 }
1192 int64_t offset = shadow_frame->GetVRegLong(arg_offset + 2);
1193 mirror::Object* expected_value = shadow_frame->GetVRegReference(arg_offset + 4);
1194 mirror::Object* newValue = shadow_frame->GetVRegReference(arg_offset + 5);
1195
1196 // Must use non transactional mode.
1197 if (kUseReadBarrier) {
1198 // Need to make sure the reference stored in the field is a to-space one before attempting the
1199 // CAS or the CAS could fail incorrectly.
1200 mirror::HeapReference<mirror::Object>* field_addr =
1201 reinterpret_cast<mirror::HeapReference<mirror::Object>*>(
1202 reinterpret_cast<uint8_t*>(obj) + static_cast<size_t>(offset));
1203 ReadBarrier::Barrier<mirror::Object, kWithReadBarrier, /*kAlwaysUpdateField*/true>(
1204 obj,
1205 MemberOffset(offset),
1206 field_addr);
1207 }
1208 bool success;
1209 // Check whether we're in a transaction, call accordingly.
1210 if (Runtime::Current()->IsActiveTransaction()) {
1211 success = obj->CasFieldStrongSequentiallyConsistentObject<true>(MemberOffset(offset),
1212 expected_value,
1213 newValue);
1214 } else {
1215 success = obj->CasFieldStrongSequentiallyConsistentObject<false>(MemberOffset(offset),
1216 expected_value,
1217 newValue);
1218 }
1219 result->SetZ(success ? 1 : 0);
1220}
1221
1222void UnstartedRuntime::UnstartedUnsafeGetObjectVolatile(
1223 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
1224 SHARED_REQUIRES(Locks::mutator_lock_) {
1225 // Argument 0 is the Unsafe instance, skip.
1226 mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset + 1);
1227 if (obj == nullptr) {
1228 AbortTransactionOrFail(self, "Cannot access null object, retry at runtime.");
1229 return;
1230 }
1231 int64_t offset = shadow_frame->GetVRegLong(arg_offset + 2);
1232 mirror::Object* value = obj->GetFieldObjectVolatile<mirror::Object>(MemberOffset(offset));
1233 result->SetL(value);
1234}
1235
Andreas Gampe8a18fde2016-04-05 21:12:51 -07001236void UnstartedRuntime::UnstartedUnsafePutObjectVolatile(
1237 Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset)
1238 SHARED_REQUIRES(Locks::mutator_lock_) {
1239 // Argument 0 is the Unsafe instance, skip.
1240 mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset + 1);
1241 if (obj == nullptr) {
1242 AbortTransactionOrFail(self, "Cannot access null object, retry at runtime.");
1243 return;
1244 }
1245 int64_t offset = shadow_frame->GetVRegLong(arg_offset + 2);
1246 mirror::Object* value = shadow_frame->GetVRegReference(arg_offset + 4);
1247 if (Runtime::Current()->IsActiveTransaction()) {
1248 obj->SetFieldObjectVolatile<true>(MemberOffset(offset), value);
1249 } else {
1250 obj->SetFieldObjectVolatile<false>(MemberOffset(offset), value);
1251 }
1252}
1253
Andreas Gampebc4d2182016-02-22 10:03:12 -08001254void UnstartedRuntime::UnstartedUnsafePutOrderedObject(
1255 Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset)
1256 SHARED_REQUIRES(Locks::mutator_lock_) {
1257 // Argument 0 is the Unsafe instance, skip.
1258 mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset + 1);
1259 if (obj == nullptr) {
1260 AbortTransactionOrFail(self, "Cannot access null object, retry at runtime.");
1261 return;
1262 }
1263 int64_t offset = shadow_frame->GetVRegLong(arg_offset + 2);
1264 mirror::Object* newValue = shadow_frame->GetVRegReference(arg_offset + 4);
1265 QuasiAtomic::ThreadFenceRelease();
1266 if (Runtime::Current()->IsActiveTransaction()) {
1267 obj->SetFieldObject<true>(MemberOffset(offset), newValue);
1268 } else {
1269 obj->SetFieldObject<false>(MemberOffset(offset), newValue);
1270 }
1271}
1272
Andreas Gampe13fc1be2016-04-05 20:14:30 -07001273// A cutout for Integer.parseInt(String). Note: this code is conservative and will bail instead
1274// of correctly handling the corner cases.
1275void UnstartedRuntime::UnstartedIntegerParseInt(
1276 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
1277 SHARED_REQUIRES(Locks::mutator_lock_) {
1278 mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset);
1279 if (obj == nullptr) {
1280 AbortTransactionOrFail(self, "Cannot parse null string, retry at runtime.");
1281 return;
1282 }
1283
1284 std::string string_value = obj->AsString()->ToModifiedUtf8();
1285 if (string_value.empty()) {
1286 AbortTransactionOrFail(self, "Cannot parse empty string, retry at runtime.");
1287 return;
1288 }
1289
1290 const char* c_str = string_value.c_str();
1291 char *end;
1292 // Can we set errno to 0? Is this always a variable, and not a macro?
1293 // Worst case, we'll incorrectly fail a transaction. Seems OK.
1294 int64_t l = strtol(c_str, &end, 10);
1295
1296 if ((errno == ERANGE && l == LONG_MAX) || l > std::numeric_limits<int32_t>::max() ||
1297 (errno == ERANGE && l == LONG_MIN) || l < std::numeric_limits<int32_t>::min()) {
1298 AbortTransactionOrFail(self, "Cannot parse string %s, retry at runtime.", c_str);
1299 return;
1300 }
1301 if (l == 0) {
1302 // Check whether the string wasn't exactly zero.
1303 if (string_value != "0") {
1304 AbortTransactionOrFail(self, "Cannot parse string %s, retry at runtime.", c_str);
1305 return;
1306 }
1307 } else if (*end != '\0') {
1308 AbortTransactionOrFail(self, "Cannot parse string %s, retry at runtime.", c_str);
1309 return;
1310 }
1311
1312 result->SetI(static_cast<int32_t>(l));
1313}
1314
1315// A cutout for Long.parseLong.
1316//
1317// Note: for now use code equivalent to Integer.parseInt, as the full range may not be supported
1318// well.
1319void UnstartedRuntime::UnstartedLongParseLong(
1320 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
1321 SHARED_REQUIRES(Locks::mutator_lock_) {
1322 mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset);
1323 if (obj == nullptr) {
1324 AbortTransactionOrFail(self, "Cannot parse null string, retry at runtime.");
1325 return;
1326 }
1327
1328 std::string string_value = obj->AsString()->ToModifiedUtf8();
1329 if (string_value.empty()) {
1330 AbortTransactionOrFail(self, "Cannot parse empty string, retry at runtime.");
1331 return;
1332 }
1333
1334 const char* c_str = string_value.c_str();
1335 char *end;
1336 // Can we set errno to 0? Is this always a variable, and not a macro?
1337 // Worst case, we'll incorrectly fail a transaction. Seems OK.
1338 int64_t l = strtol(c_str, &end, 10);
1339
1340 // Note: comparing against int32_t min/max is intentional here.
1341 if ((errno == ERANGE && l == LONG_MAX) || l > std::numeric_limits<int32_t>::max() ||
1342 (errno == ERANGE && l == LONG_MIN) || l < std::numeric_limits<int32_t>::min()) {
1343 AbortTransactionOrFail(self, "Cannot parse string %s, retry at runtime.", c_str);
1344 return;
1345 }
1346 if (l == 0) {
1347 // Check whether the string wasn't exactly zero.
1348 if (string_value != "0") {
1349 AbortTransactionOrFail(self, "Cannot parse string %s, retry at runtime.", c_str);
1350 return;
1351 }
1352 } else if (*end != '\0') {
1353 AbortTransactionOrFail(self, "Cannot parse string %s, retry at runtime.", c_str);
1354 return;
1355 }
1356
1357 result->SetJ(l);
1358}
1359
Andreas Gampebc4d2182016-02-22 10:03:12 -08001360
Mathieu Chartiere401d142015-04-22 13:56:20 -07001361void UnstartedRuntime::UnstartedJNIVMRuntimeNewUnpaddedArray(
1362 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
1363 uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001364 int32_t length = args[1];
1365 DCHECK_GE(length, 0);
1366 mirror::Class* element_class = reinterpret_cast<mirror::Object*>(args[0])->AsClass();
1367 Runtime* runtime = Runtime::Current();
1368 mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(self, &element_class);
1369 DCHECK(array_class != nullptr);
1370 gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
1371 result->SetL(mirror::Array::Alloc<true, true>(self, array_class, length,
1372 array_class->GetComponentSizeShift(), allocator));
1373}
1374
Mathieu Chartiere401d142015-04-22 13:56:20 -07001375void UnstartedRuntime::UnstartedJNIVMStackGetCallingClassLoader(
1376 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1377 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001378 result->SetL(nullptr);
1379}
1380
Mathieu Chartiere401d142015-04-22 13:56:20 -07001381void UnstartedRuntime::UnstartedJNIVMStackGetStackClass2(
1382 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
1383 uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001384 NthCallerVisitor visitor(self, 3);
1385 visitor.WalkStack();
1386 if (visitor.caller != nullptr) {
1387 result->SetL(visitor.caller->GetDeclaringClass());
1388 }
1389}
1390
Mathieu Chartiere401d142015-04-22 13:56:20 -07001391void UnstartedRuntime::UnstartedJNIMathLog(
1392 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1393 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001394 JValue value;
1395 value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
1396 result->SetD(log(value.GetD()));
1397}
1398
Mathieu Chartiere401d142015-04-22 13:56:20 -07001399void UnstartedRuntime::UnstartedJNIMathExp(
1400 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1401 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001402 JValue value;
1403 value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
1404 result->SetD(exp(value.GetD()));
1405}
1406
Andreas Gampebc4d2182016-02-22 10:03:12 -08001407void UnstartedRuntime::UnstartedJNIAtomicLongVMSupportsCS8(
1408 Thread* self ATTRIBUTE_UNUSED,
1409 ArtMethod* method ATTRIBUTE_UNUSED,
1410 mirror::Object* receiver ATTRIBUTE_UNUSED,
1411 uint32_t* args ATTRIBUTE_UNUSED,
1412 JValue* result) {
1413 result->SetZ(QuasiAtomic::LongAtomicsUseMutexes(Runtime::Current()->GetInstructionSet())
1414 ? 0
1415 : 1);
1416}
1417
Mathieu Chartiere401d142015-04-22 13:56:20 -07001418void UnstartedRuntime::UnstartedJNIClassGetNameNative(
1419 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver,
1420 uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001421 StackHandleScope<1> hs(self);
1422 result->SetL(mirror::Class::ComputeName(hs.NewHandle(receiver->AsClass())));
1423}
1424
Andreas Gampebc4d2182016-02-22 10:03:12 -08001425void UnstartedRuntime::UnstartedJNIDoubleLongBitsToDouble(
1426 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1427 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
1428 uint64_t long_input = args[0] | (static_cast<uint64_t>(args[1]) << 32);
1429 result->SetD(bit_cast<double>(long_input));
1430}
1431
Mathieu Chartiere401d142015-04-22 13:56:20 -07001432void UnstartedRuntime::UnstartedJNIFloatFloatToRawIntBits(
1433 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1434 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001435 result->SetI(args[0]);
1436}
1437
Mathieu Chartiere401d142015-04-22 13:56:20 -07001438void UnstartedRuntime::UnstartedJNIFloatIntBitsToFloat(
1439 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1440 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001441 result->SetI(args[0]);
1442}
1443
Mathieu Chartiere401d142015-04-22 13:56:20 -07001444void UnstartedRuntime::UnstartedJNIObjectInternalClone(
1445 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver,
1446 uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001447 result->SetL(receiver->Clone(self));
1448}
1449
Mathieu Chartiere401d142015-04-22 13:56:20 -07001450void UnstartedRuntime::UnstartedJNIObjectNotifyAll(
1451 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver,
1452 uint32_t* args ATTRIBUTE_UNUSED, JValue* result ATTRIBUTE_UNUSED) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001453 receiver->NotifyAll(self);
1454}
1455
Mathieu Chartiere401d142015-04-22 13:56:20 -07001456void UnstartedRuntime::UnstartedJNIStringCompareTo(
1457 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver, uint32_t* args,
1458 JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001459 mirror::String* rhs = reinterpret_cast<mirror::Object*>(args[0])->AsString();
1460 if (rhs == nullptr) {
Andreas Gampe068b0c02015-03-11 12:44:47 -07001461 AbortTransactionOrFail(self, "String.compareTo with null object");
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001462 }
1463 result->SetI(receiver->AsString()->CompareTo(rhs));
1464}
1465
Mathieu Chartiere401d142015-04-22 13:56:20 -07001466void UnstartedRuntime::UnstartedJNIStringIntern(
1467 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver,
1468 uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001469 result->SetL(receiver->AsString()->Intern());
1470}
1471
Mathieu Chartiere401d142015-04-22 13:56:20 -07001472void UnstartedRuntime::UnstartedJNIStringFastIndexOf(
1473 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver,
1474 uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001475 result->SetI(receiver->AsString()->FastIndexOf(args[0], args[1]));
1476}
1477
Mathieu Chartiere401d142015-04-22 13:56:20 -07001478void UnstartedRuntime::UnstartedJNIArrayCreateMultiArray(
1479 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
1480 uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001481 StackHandleScope<2> hs(self);
1482 auto h_class(hs.NewHandle(reinterpret_cast<mirror::Class*>(args[0])->AsClass()));
1483 auto h_dimensions(hs.NewHandle(reinterpret_cast<mirror::IntArray*>(args[1])->AsIntArray()));
1484 result->SetL(mirror::Array::CreateMultiArray(self, h_class, h_dimensions));
1485}
1486
Mathieu Chartiere401d142015-04-22 13:56:20 -07001487void UnstartedRuntime::UnstartedJNIArrayCreateObjectArray(
1488 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
1489 uint32_t* args, JValue* result) {
Andreas Gampee598e042015-04-10 14:57:10 -07001490 int32_t length = static_cast<int32_t>(args[1]);
1491 if (length < 0) {
1492 ThrowNegativeArraySizeException(length);
1493 return;
1494 }
1495 mirror::Class* element_class = reinterpret_cast<mirror::Class*>(args[0])->AsClass();
1496 Runtime* runtime = Runtime::Current();
1497 ClassLinker* class_linker = runtime->GetClassLinker();
1498 mirror::Class* array_class = class_linker->FindArrayClass(self, &element_class);
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001499 if (UNLIKELY(array_class == nullptr)) {
Andreas Gampee598e042015-04-10 14:57:10 -07001500 CHECK(self->IsExceptionPending());
1501 return;
1502 }
1503 DCHECK(array_class->IsObjectArrayClass());
1504 mirror::Array* new_array = mirror::ObjectArray<mirror::Object*>::Alloc(
1505 self, array_class, length, runtime->GetHeap()->GetCurrentAllocator());
1506 result->SetL(new_array);
1507}
1508
Mathieu Chartiere401d142015-04-22 13:56:20 -07001509void UnstartedRuntime::UnstartedJNIThrowableNativeFillInStackTrace(
1510 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
1511 uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001512 ScopedObjectAccessUnchecked soa(self);
1513 if (Runtime::Current()->IsActiveTransaction()) {
1514 result->SetL(soa.Decode<mirror::Object*>(self->CreateInternalStackTrace<true>(soa)));
1515 } else {
1516 result->SetL(soa.Decode<mirror::Object*>(self->CreateInternalStackTrace<false>(soa)));
1517 }
1518}
1519
Mathieu Chartiere401d142015-04-22 13:56:20 -07001520void UnstartedRuntime::UnstartedJNISystemIdentityHashCode(
1521 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1522 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001523 mirror::Object* obj = reinterpret_cast<mirror::Object*>(args[0]);
1524 result->SetI((obj != nullptr) ? obj->IdentityHashCode() : 0);
1525}
1526
Mathieu Chartiere401d142015-04-22 13:56:20 -07001527void UnstartedRuntime::UnstartedJNIByteOrderIsLittleEndian(
1528 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1529 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001530 result->SetZ(JNI_TRUE);
1531}
1532
Mathieu Chartiere401d142015-04-22 13:56:20 -07001533void UnstartedRuntime::UnstartedJNIUnsafeCompareAndSwapInt(
1534 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1535 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001536 mirror::Object* obj = reinterpret_cast<mirror::Object*>(args[0]);
1537 jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1];
1538 jint expectedValue = args[3];
1539 jint newValue = args[4];
1540 bool success;
1541 if (Runtime::Current()->IsActiveTransaction()) {
1542 success = obj->CasFieldStrongSequentiallyConsistent32<true>(MemberOffset(offset),
1543 expectedValue, newValue);
1544 } else {
1545 success = obj->CasFieldStrongSequentiallyConsistent32<false>(MemberOffset(offset),
1546 expectedValue, newValue);
1547 }
1548 result->SetZ(success ? JNI_TRUE : JNI_FALSE);
1549}
1550
Narayan Kamath34a316f2016-03-30 13:11:18 +01001551void UnstartedRuntime::UnstartedJNIUnsafeGetIntVolatile(
1552 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
1553 uint32_t* args, JValue* result) {
1554 mirror::Object* obj = reinterpret_cast<mirror::Object*>(args[0]);
1555 if (obj == nullptr) {
1556 AbortTransactionOrFail(self, "Cannot access null object, retry at runtime.");
1557 return;
1558 }
1559
1560 jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1];
1561 result->SetI(obj->GetField32Volatile(MemberOffset(offset)));
1562}
1563
Mathieu Chartiere401d142015-04-22 13:56:20 -07001564void UnstartedRuntime::UnstartedJNIUnsafePutObject(
1565 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1566 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result ATTRIBUTE_UNUSED) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001567 mirror::Object* obj = reinterpret_cast<mirror::Object*>(args[0]);
1568 jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1];
1569 mirror::Object* newValue = reinterpret_cast<mirror::Object*>(args[3]);
1570 if (Runtime::Current()->IsActiveTransaction()) {
1571 obj->SetFieldObject<true>(MemberOffset(offset), newValue);
1572 } else {
1573 obj->SetFieldObject<false>(MemberOffset(offset), newValue);
1574 }
1575}
1576
Andreas Gampe799681b2015-05-15 19:24:12 -07001577void UnstartedRuntime::UnstartedJNIUnsafeGetArrayBaseOffsetForComponentType(
Mathieu Chartiere401d142015-04-22 13:56:20 -07001578 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1579 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001580 mirror::Class* component = reinterpret_cast<mirror::Object*>(args[0])->AsClass();
1581 Primitive::Type primitive_type = component->GetPrimitiveType();
1582 result->SetI(mirror::Array::DataOffset(Primitive::ComponentSize(primitive_type)).Int32Value());
1583}
1584
Andreas Gampe799681b2015-05-15 19:24:12 -07001585void UnstartedRuntime::UnstartedJNIUnsafeGetArrayIndexScaleForComponentType(
Mathieu Chartiere401d142015-04-22 13:56:20 -07001586 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1587 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001588 mirror::Class* component = reinterpret_cast<mirror::Object*>(args[0])->AsClass();
1589 Primitive::Type primitive_type = component->GetPrimitiveType();
1590 result->SetI(Primitive::ComponentSize(primitive_type));
1591}
1592
Andreas Gampedd9d0552015-03-09 12:57:41 -07001593typedef void (*InvokeHandler)(Thread* self, ShadowFrame* shadow_frame, JValue* result,
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001594 size_t arg_size);
1595
Mathieu Chartiere401d142015-04-22 13:56:20 -07001596typedef void (*JNIHandler)(Thread* self, ArtMethod* method, mirror::Object* receiver,
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001597 uint32_t* args, JValue* result);
1598
1599static bool tables_initialized_ = false;
1600static std::unordered_map<std::string, InvokeHandler> invoke_handlers_;
1601static std::unordered_map<std::string, JNIHandler> jni_handlers_;
1602
Andreas Gampe799681b2015-05-15 19:24:12 -07001603void UnstartedRuntime::InitializeInvokeHandlers() {
1604#define UNSTARTED_DIRECT(ShortName, Sig) \
1605 invoke_handlers_.insert(std::make_pair(Sig, & UnstartedRuntime::Unstarted ## ShortName));
1606#include "unstarted_runtime_list.h"
1607 UNSTARTED_RUNTIME_DIRECT_LIST(UNSTARTED_DIRECT)
1608#undef UNSTARTED_RUNTIME_DIRECT_LIST
1609#undef UNSTARTED_RUNTIME_JNI_LIST
1610#undef UNSTARTED_DIRECT
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001611}
1612
Andreas Gampe799681b2015-05-15 19:24:12 -07001613void UnstartedRuntime::InitializeJNIHandlers() {
1614#define UNSTARTED_JNI(ShortName, Sig) \
1615 jni_handlers_.insert(std::make_pair(Sig, & UnstartedRuntime::UnstartedJNI ## ShortName));
1616#include "unstarted_runtime_list.h"
1617 UNSTARTED_RUNTIME_JNI_LIST(UNSTARTED_JNI)
1618#undef UNSTARTED_RUNTIME_DIRECT_LIST
1619#undef UNSTARTED_RUNTIME_JNI_LIST
1620#undef UNSTARTED_JNI
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001621}
1622
Andreas Gampe799681b2015-05-15 19:24:12 -07001623void UnstartedRuntime::Initialize() {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001624 CHECK(!tables_initialized_);
1625
Andreas Gampe799681b2015-05-15 19:24:12 -07001626 InitializeInvokeHandlers();
1627 InitializeJNIHandlers();
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001628
1629 tables_initialized_ = true;
1630}
1631
Andreas Gampe799681b2015-05-15 19:24:12 -07001632void UnstartedRuntime::Invoke(Thread* self, const DexFile::CodeItem* code_item,
1633 ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001634 // In a runtime that's not started we intercept certain methods to avoid complicated dependency
1635 // problems in core libraries.
1636 CHECK(tables_initialized_);
1637
1638 std::string name(PrettyMethod(shadow_frame->GetMethod()));
1639 const auto& iter = invoke_handlers_.find(name);
1640 if (iter != invoke_handlers_.end()) {
Kenny Root57f91e82015-05-14 15:58:17 -07001641 // Clear out the result in case it's not zeroed out.
1642 result->SetL(0);
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001643 (*iter->second)(self, shadow_frame, result, arg_offset);
1644 } else {
1645 // Not special, continue with regular interpreter execution.
Andreas Gampe3cfa4d02015-10-06 17:04:01 -07001646 ArtInterpreterToInterpreterBridge(self, code_item, shadow_frame, result);
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001647 }
1648}
1649
1650// 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 -07001651void UnstartedRuntime::Jni(Thread* self, ArtMethod* method, mirror::Object* receiver,
Andreas Gampe799681b2015-05-15 19:24:12 -07001652 uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001653 std::string name(PrettyMethod(method));
1654 const auto& iter = jni_handlers_.find(name);
1655 if (iter != jni_handlers_.end()) {
Kenny Root57f91e82015-05-14 15:58:17 -07001656 // Clear out the result in case it's not zeroed out.
1657 result->SetL(0);
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001658 (*iter->second)(self, method, receiver, args, result);
1659 } else if (Runtime::Current()->IsActiveTransaction()) {
Sebastien Hertz45b15972015-04-03 16:07:05 +02001660 AbortTransactionF(self, "Attempt to invoke native method in non-started runtime: %s",
1661 name.c_str());
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001662 } else {
1663 LOG(FATAL) << "Calling native method " << PrettyMethod(method) << " in an unstarted "
1664 "non-transactional runtime";
1665 }
1666}
1667
1668} // namespace interpreter
1669} // namespace art