blob: 0e175b85eb53a2a47b3fdf6726d2681e83e27a04 [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
19#include <cmath>
20#include <unordered_map>
21
Andreas Gampeaacc25d2015-04-01 14:49:06 -070022#include "ScopedLocalRef.h"
23
Mathieu Chartiere401d142015-04-22 13:56:20 -070024#include "art_method-inl.h"
Andreas Gampe2969bcd2015-03-09 12:57:41 -070025#include "base/logging.h"
26#include "base/macros.h"
27#include "class_linker.h"
28#include "common_throws.h"
29#include "entrypoints/entrypoint_utils-inl.h"
30#include "handle_scope-inl.h"
31#include "interpreter/interpreter_common.h"
32#include "mirror/array-inl.h"
Andreas Gampe2969bcd2015-03-09 12:57:41 -070033#include "mirror/class.h"
Mathieu Chartierdaaf3262015-03-24 13:30:28 -070034#include "mirror/field-inl.h"
Andreas Gampe2969bcd2015-03-09 12:57:41 -070035#include "mirror/object-inl.h"
36#include "mirror/object_array-inl.h"
37#include "mirror/string-inl.h"
38#include "nth_caller_visitor.h"
39#include "thread.h"
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020040#include "transaction.h"
Andreas Gampe2969bcd2015-03-09 12:57:41 -070041#include "well_known_classes.h"
Andreas Gampef778eb22015-04-13 14:17:09 -070042#include "zip_archive.h"
Andreas Gampe2969bcd2015-03-09 12:57:41 -070043
44namespace art {
45namespace interpreter {
46
Andreas Gampe068b0c02015-03-11 12:44:47 -070047static void AbortTransactionOrFail(Thread* self, const char* fmt, ...)
Sebastien Hertz45b15972015-04-03 16:07:05 +020048 __attribute__((__format__(__printf__, 2, 3)))
Mathieu Chartier90443472015-07-16 20:32:27 -070049 SHARED_REQUIRES(Locks::mutator_lock_);
Sebastien Hertz45b15972015-04-03 16:07:05 +020050
51static void AbortTransactionOrFail(Thread* self, const char* fmt, ...) {
Andreas Gampe068b0c02015-03-11 12:44:47 -070052 va_list args;
Andreas Gampe068b0c02015-03-11 12:44:47 -070053 if (Runtime::Current()->IsActiveTransaction()) {
Sebastien Hertz45b15972015-04-03 16:07:05 +020054 va_start(args, fmt);
55 AbortTransactionV(self, fmt, args);
Andreas Gampe068b0c02015-03-11 12:44:47 -070056 va_end(args);
57 } else {
Sebastien Hertz45b15972015-04-03 16:07:05 +020058 va_start(args, fmt);
59 std::string msg;
60 StringAppendV(&msg, fmt, args);
61 va_end(args);
62 LOG(FATAL) << "Trying to abort, but not in transaction mode: " << msg;
Andreas Gampe068b0c02015-03-11 12:44:47 -070063 UNREACHABLE();
64 }
65}
66
Andreas Gampe2969bcd2015-03-09 12:57:41 -070067// Helper function to deal with class loading in an unstarted runtime.
68static void UnstartedRuntimeFindClass(Thread* self, Handle<mirror::String> className,
69 Handle<mirror::ClassLoader> class_loader, JValue* result,
70 const std::string& method_name, bool initialize_class,
71 bool abort_if_not_found)
Mathieu Chartier90443472015-07-16 20:32:27 -070072 SHARED_REQUIRES(Locks::mutator_lock_) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -070073 CHECK(className.Get() != nullptr);
74 std::string descriptor(DotToDescriptor(className->ToModifiedUtf8().c_str()));
75 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
76
77 mirror::Class* found = class_linker->FindClass(self, descriptor.c_str(), class_loader);
78 if (found == nullptr && abort_if_not_found) {
79 if (!self->IsExceptionPending()) {
Andreas Gampe068b0c02015-03-11 12:44:47 -070080 AbortTransactionOrFail(self, "%s failed in un-started runtime for class: %s",
81 method_name.c_str(), PrettyDescriptor(descriptor.c_str()).c_str());
Andreas Gampe2969bcd2015-03-09 12:57:41 -070082 }
83 return;
84 }
85 if (found != nullptr && initialize_class) {
86 StackHandleScope<1> hs(self);
87 Handle<mirror::Class> h_class(hs.NewHandle(found));
88 if (!class_linker->EnsureInitialized(self, h_class, true, true)) {
89 CHECK(self->IsExceptionPending());
90 return;
91 }
92 }
93 result->SetL(found);
94}
95
96// Common helper for class-loading cutouts in an unstarted runtime. We call Runtime methods that
97// rely on Java code to wrap errors in the correct exception class (i.e., NoClassDefFoundError into
98// ClassNotFoundException), so need to do the same. The only exception is if the exception is
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020099// actually the transaction abort exception. This must not be wrapped, as it signals an
100// initialization abort.
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700101static void CheckExceptionGenerateClassNotFound(Thread* self)
Mathieu Chartier90443472015-07-16 20:32:27 -0700102 SHARED_REQUIRES(Locks::mutator_lock_) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700103 if (self->IsExceptionPending()) {
Sebastien Hertz2fd7e692015-04-02 11:11:19 +0200104 // If it is not the transaction abort exception, wrap it.
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700105 std::string type(PrettyTypeOf(self->GetException()));
Sebastien Hertz2fd7e692015-04-02 11:11:19 +0200106 if (type != Transaction::kAbortExceptionDescriptor) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700107 self->ThrowNewWrappedException("Ljava/lang/ClassNotFoundException;",
108 "ClassNotFoundException");
109 }
110 }
111}
112
Andreas Gampe5d4bb1d2015-04-14 22:16:14 -0700113static mirror::String* GetClassName(Thread* self, ShadowFrame* shadow_frame, size_t arg_offset)
Mathieu Chartier90443472015-07-16 20:32:27 -0700114 SHARED_REQUIRES(Locks::mutator_lock_) {
Andreas Gampe5d4bb1d2015-04-14 22:16:14 -0700115 mirror::Object* param = shadow_frame->GetVRegReference(arg_offset);
116 if (param == nullptr) {
117 AbortTransactionOrFail(self, "Null-pointer in Class.forName.");
118 return nullptr;
119 }
120 return param->AsString();
121}
122
Andreas Gampe799681b2015-05-15 19:24:12 -0700123void UnstartedRuntime::UnstartedClassForName(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700124 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe5d4bb1d2015-04-14 22:16:14 -0700125 mirror::String* class_name = GetClassName(self, shadow_frame, arg_offset);
126 if (class_name == nullptr) {
127 return;
128 }
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700129 StackHandleScope<1> hs(self);
130 Handle<mirror::String> h_class_name(hs.NewHandle(class_name));
Mathieu Chartier9865bde2015-12-21 09:58:16 -0800131 UnstartedRuntimeFindClass(self,
132 h_class_name,
133 ScopedNullHandle<mirror::ClassLoader>(),
134 result,
135 "Class.forName",
136 true,
137 false);
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700138 CheckExceptionGenerateClassNotFound(self);
139}
140
Andreas Gampe799681b2015-05-15 19:24:12 -0700141void UnstartedRuntime::UnstartedClassForNameLong(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700142 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe5d4bb1d2015-04-14 22:16:14 -0700143 mirror::String* class_name = GetClassName(self, shadow_frame, arg_offset);
144 if (class_name == nullptr) {
Andreas Gampebf4d3af2015-04-14 10:10:33 -0700145 return;
146 }
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700147 bool initialize_class = shadow_frame->GetVReg(arg_offset + 1) != 0;
148 mirror::ClassLoader* class_loader =
149 down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset + 2));
150 StackHandleScope<2> hs(self);
151 Handle<mirror::String> h_class_name(hs.NewHandle(class_name));
152 Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(class_loader));
153 UnstartedRuntimeFindClass(self, h_class_name, h_class_loader, result, "Class.forName",
154 initialize_class, false);
155 CheckExceptionGenerateClassNotFound(self);
156}
157
Andreas Gampe799681b2015-05-15 19:24:12 -0700158void UnstartedRuntime::UnstartedClassClassForName(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700159 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe5d4bb1d2015-04-14 22:16:14 -0700160 mirror::String* class_name = GetClassName(self, shadow_frame, arg_offset);
161 if (class_name == nullptr) {
162 return;
163 }
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700164 bool initialize_class = shadow_frame->GetVReg(arg_offset + 1) != 0;
165 mirror::ClassLoader* class_loader =
166 down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset + 2));
167 StackHandleScope<2> hs(self);
168 Handle<mirror::String> h_class_name(hs.NewHandle(class_name));
169 Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(class_loader));
170 UnstartedRuntimeFindClass(self, h_class_name, h_class_loader, result, "Class.classForName",
171 initialize_class, false);
172 CheckExceptionGenerateClassNotFound(self);
173}
174
Andreas Gampe799681b2015-05-15 19:24:12 -0700175void UnstartedRuntime::UnstartedClassNewInstance(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700176 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
177 StackHandleScope<2> hs(self); // Class, constructor, object.
Andreas Gampe5d4bb1d2015-04-14 22:16:14 -0700178 mirror::Object* param = shadow_frame->GetVRegReference(arg_offset);
179 if (param == nullptr) {
180 AbortTransactionOrFail(self, "Null-pointer in Class.newInstance.");
181 return;
182 }
183 mirror::Class* klass = param->AsClass();
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700184 Handle<mirror::Class> h_klass(hs.NewHandle(klass));
Andreas Gampe0f7e3d62015-03-11 13:24:35 -0700185
186 // Check that it's not null.
187 if (h_klass.Get() == nullptr) {
188 AbortTransactionOrFail(self, "Class reference is null for newInstance");
189 return;
190 }
191
192 // If we're in a transaction, class must not be finalizable (it or a superclass has a finalizer).
193 if (Runtime::Current()->IsActiveTransaction()) {
194 if (h_klass.Get()->IsFinalizable()) {
Sebastien Hertz45b15972015-04-03 16:07:05 +0200195 AbortTransactionF(self, "Class for newInstance is finalizable: '%s'",
196 PrettyClass(h_klass.Get()).c_str());
Andreas Gampe0f7e3d62015-03-11 13:24:35 -0700197 return;
198 }
199 }
200
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700201 // There are two situations in which we'll abort this run.
202 // 1) If the class isn't yet initialized and initialization fails.
203 // 2) If we can't find the default constructor. We'll postpone the exception to runtime.
204 // Note that 2) could likely be handled here, but for safety abort the transaction.
205 bool ok = false;
Mathieu Chartiere401d142015-04-22 13:56:20 -0700206 auto* cl = Runtime::Current()->GetClassLinker();
207 if (cl->EnsureInitialized(self, h_klass, true, true)) {
208 auto* cons = h_klass->FindDeclaredDirectMethod("<init>", "()V", cl->GetImagePointerSize());
209 if (cons != nullptr) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700210 Handle<mirror::Object> h_obj(hs.NewHandle(klass->AllocObject(self)));
211 CHECK(h_obj.Get() != nullptr); // We don't expect OOM at compile-time.
Mathieu Chartiere401d142015-04-22 13:56:20 -0700212 EnterInterpreterFromInvoke(self, cons, h_obj.Get(), nullptr, nullptr);
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700213 if (!self->IsExceptionPending()) {
214 result->SetL(h_obj.Get());
215 ok = true;
216 }
217 } else {
218 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
219 "Could not find default constructor for '%s'",
220 PrettyClass(h_klass.Get()).c_str());
221 }
222 }
223 if (!ok) {
Andreas Gampe068b0c02015-03-11 12:44:47 -0700224 AbortTransactionOrFail(self, "Failed in Class.newInstance for '%s' with %s",
225 PrettyClass(h_klass.Get()).c_str(),
226 PrettyTypeOf(self->GetException()).c_str());
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700227 }
228}
229
Andreas Gampe799681b2015-05-15 19:24:12 -0700230void UnstartedRuntime::UnstartedClassGetDeclaredField(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700231 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700232 // Special managed code cut-out to allow field lookup in a un-started runtime that'd fail
233 // going the reflective Dex way.
234 mirror::Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
235 mirror::String* name2 = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
Mathieu Chartierc7853442015-03-27 14:35:38 -0700236 ArtField* found = nullptr;
Mathieu Chartier54d220e2015-07-30 16:20:06 -0700237 for (ArtField& field : klass->GetIFields()) {
238 if (name2->Equals(field.GetName())) {
239 found = &field;
Mathieu Chartierc7853442015-03-27 14:35:38 -0700240 break;
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700241 }
242 }
243 if (found == nullptr) {
Mathieu Chartier54d220e2015-07-30 16:20:06 -0700244 for (ArtField& field : klass->GetSFields()) {
245 if (name2->Equals(field.GetName())) {
246 found = &field;
Mathieu Chartierc7853442015-03-27 14:35:38 -0700247 break;
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700248 }
249 }
250 }
Andreas Gampe068b0c02015-03-11 12:44:47 -0700251 if (found == nullptr) {
252 AbortTransactionOrFail(self, "Failed to find field in Class.getDeclaredField in un-started "
253 " runtime. name=%s class=%s", name2->ToModifiedUtf8().c_str(),
254 PrettyDescriptor(klass).c_str());
255 return;
256 }
Mathieu Chartierdaaf3262015-03-24 13:30:28 -0700257 if (Runtime::Current()->IsActiveTransaction()) {
258 result->SetL(mirror::Field::CreateFromArtField<true>(self, found, true));
259 } else {
260 result->SetL(mirror::Field::CreateFromArtField<false>(self, found, true));
261 }
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700262}
263
Andreas Gampe633750c2016-02-19 10:49:50 -0800264void UnstartedRuntime::UnstartedClassGetEnclosingClass(
265 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
266 StackHandleScope<1> hs(self);
267 Handle<mirror::Class> klass(hs.NewHandle(shadow_frame->GetVRegReference(arg_offset)->AsClass()));
268 if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
269 result->SetL(nullptr);
270 }
271 result->SetL(klass->GetDexFile().GetEnclosingClass(klass));
272}
273
Andreas Gampe799681b2015-05-15 19:24:12 -0700274void UnstartedRuntime::UnstartedVmClassLoaderFindLoadedClass(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700275 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700276 mirror::String* class_name = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
277 mirror::ClassLoader* class_loader =
278 down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset));
279 StackHandleScope<2> hs(self);
280 Handle<mirror::String> h_class_name(hs.NewHandle(class_name));
281 Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(class_loader));
282 UnstartedRuntimeFindClass(self, h_class_name, h_class_loader, result,
283 "VMClassLoader.findLoadedClass", false, false);
284 // This might have an error pending. But semantics are to just return null.
285 if (self->IsExceptionPending()) {
286 // If it is an InternalError, keep it. See CheckExceptionGenerateClassNotFound.
287 std::string type(PrettyTypeOf(self->GetException()));
288 if (type != "java.lang.InternalError") {
289 self->ClearException();
290 }
291 }
292}
293
Mathieu Chartiere401d142015-04-22 13:56:20 -0700294void UnstartedRuntime::UnstartedVoidLookupType(
295 Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame ATTRIBUTE_UNUSED, JValue* result,
296 size_t arg_offset ATTRIBUTE_UNUSED) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700297 result->SetL(Runtime::Current()->GetClassLinker()->FindPrimitiveClass('V'));
298}
299
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700300// Arraycopy emulation.
301// Note: we can't use any fast copy functions, as they are not available under transaction.
302
303template <typename T>
304static void PrimitiveArrayCopy(Thread* self,
305 mirror::Array* src_array, int32_t src_pos,
306 mirror::Array* dst_array, int32_t dst_pos,
307 int32_t length)
Mathieu Chartier90443472015-07-16 20:32:27 -0700308 SHARED_REQUIRES(Locks::mutator_lock_) {
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700309 if (src_array->GetClass()->GetComponentType() != dst_array->GetClass()->GetComponentType()) {
310 AbortTransactionOrFail(self, "Types mismatched in arraycopy: %s vs %s.",
311 PrettyDescriptor(src_array->GetClass()->GetComponentType()).c_str(),
312 PrettyDescriptor(dst_array->GetClass()->GetComponentType()).c_str());
313 return;
314 }
315 mirror::PrimitiveArray<T>* src = down_cast<mirror::PrimitiveArray<T>*>(src_array);
316 mirror::PrimitiveArray<T>* dst = down_cast<mirror::PrimitiveArray<T>*>(dst_array);
317 const bool copy_forward = (dst_pos < src_pos) || (dst_pos - src_pos >= length);
318 if (copy_forward) {
319 for (int32_t i = 0; i < length; ++i) {
320 dst->Set(dst_pos + i, src->Get(src_pos + i));
321 }
322 } else {
323 for (int32_t i = 1; i <= length; ++i) {
324 dst->Set(dst_pos + length - i, src->Get(src_pos + length - i));
325 }
326 }
327}
328
Andreas Gampe799681b2015-05-15 19:24:12 -0700329void UnstartedRuntime::UnstartedSystemArraycopy(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700330 Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700331 // Special case array copying without initializing System.
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700332 jint src_pos = shadow_frame->GetVReg(arg_offset + 1);
333 jint dst_pos = shadow_frame->GetVReg(arg_offset + 3);
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700334 jint length = shadow_frame->GetVReg(arg_offset + 4);
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700335 mirror::Array* src_array = shadow_frame->GetVRegReference(arg_offset)->AsArray();
336 mirror::Array* dst_array = shadow_frame->GetVRegReference(arg_offset + 2)->AsArray();
337
338 // Null checking.
339 if (src_array == nullptr) {
340 AbortTransactionOrFail(self, "src is null in arraycopy.");
341 return;
342 }
343 if (dst_array == nullptr) {
344 AbortTransactionOrFail(self, "dst is null in arraycopy.");
345 return;
346 }
347
348 // Bounds checking.
349 if (UNLIKELY(src_pos < 0) || UNLIKELY(dst_pos < 0) || UNLIKELY(length < 0) ||
350 UNLIKELY(src_pos > src_array->GetLength() - length) ||
351 UNLIKELY(dst_pos > dst_array->GetLength() - length)) {
352 self->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
353 "src.length=%d srcPos=%d dst.length=%d dstPos=%d length=%d",
354 src_array->GetLength(), src_pos, dst_array->GetLength(), dst_pos,
355 length);
356 AbortTransactionOrFail(self, "Index out of bounds.");
357 return;
358 }
359
360 // Type checking.
361 mirror::Class* src_type = shadow_frame->GetVRegReference(arg_offset)->GetClass()->
362 GetComponentType();
363
364 if (!src_type->IsPrimitive()) {
365 // Check that the second type is not primitive.
366 mirror::Class* trg_type = shadow_frame->GetVRegReference(arg_offset + 2)->GetClass()->
367 GetComponentType();
368 if (trg_type->IsPrimitiveInt()) {
369 AbortTransactionOrFail(self, "Type mismatch in arraycopy: %s vs %s",
370 PrettyDescriptor(src_array->GetClass()->GetComponentType()).c_str(),
371 PrettyDescriptor(dst_array->GetClass()->GetComponentType()).c_str());
372 return;
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700373 }
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700374
375 // For simplicity only do this if the component types are the same. Otherwise we have to copy
376 // even more code from the object-array functions.
377 if (src_type != trg_type) {
378 AbortTransactionOrFail(self, "Types not the same in arraycopy: %s vs %s",
379 PrettyDescriptor(src_array->GetClass()->GetComponentType()).c_str(),
380 PrettyDescriptor(dst_array->GetClass()->GetComponentType()).c_str());
381 return;
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700382 }
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700383
384 mirror::ObjectArray<mirror::Object>* src = src_array->AsObjectArray<mirror::Object>();
385 mirror::ObjectArray<mirror::Object>* dst = dst_array->AsObjectArray<mirror::Object>();
386 if (src == dst) {
387 // Can overlap, but not have type mismatches.
388 const bool copy_forward = (dst_pos < src_pos) || (dst_pos - src_pos >= length);
389 if (copy_forward) {
390 for (int32_t i = 0; i < length; ++i) {
391 dst->Set(dst_pos + i, src->Get(src_pos + i));
392 }
393 } else {
394 for (int32_t i = 1; i <= length; ++i) {
395 dst->Set(dst_pos + length - i, src->Get(src_pos + length - i));
396 }
397 }
398 } else {
399 // Can't overlap. Would need type checks, but we abort above.
400 for (int32_t i = 0; i < length; ++i) {
401 dst->Set(dst_pos + i, src->Get(src_pos + i));
402 }
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700403 }
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700404 } else if (src_type->IsPrimitiveChar()) {
405 PrimitiveArrayCopy<uint16_t>(self, src_array, src_pos, dst_array, dst_pos, length);
406 } else if (src_type->IsPrimitiveInt()) {
407 PrimitiveArrayCopy<int32_t>(self, src_array, src_pos, dst_array, dst_pos, length);
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700408 } else {
Andreas Gampe068b0c02015-03-11 12:44:47 -0700409 AbortTransactionOrFail(self, "Unimplemented System.arraycopy for type '%s'",
Andreas Gampe8e6c3fd2015-03-11 18:34:44 -0700410 PrettyDescriptor(src_type).c_str());
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700411 }
412}
413
Andreas Gampe799681b2015-05-15 19:24:12 -0700414void UnstartedRuntime::UnstartedSystemArraycopyChar(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700415 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe799681b2015-05-15 19:24:12 -0700416 // Just forward.
417 UnstartedRuntime::UnstartedSystemArraycopy(self, shadow_frame, result, arg_offset);
418}
419
420void UnstartedRuntime::UnstartedSystemArraycopyInt(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700421 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe799681b2015-05-15 19:24:12 -0700422 // Just forward.
423 UnstartedRuntime::UnstartedSystemArraycopy(self, shadow_frame, result, arg_offset);
424}
425
426void UnstartedRuntime::UnstartedThreadLocalGet(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700427 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset ATTRIBUTE_UNUSED) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700428 std::string caller(PrettyMethod(shadow_frame->GetLink()->GetMethod()));
429 bool ok = false;
430 if (caller == "java.lang.String java.lang.IntegralToString.convertInt"
431 "(java.lang.AbstractStringBuilder, int)") {
432 // Allocate non-threadlocal buffer.
433 result->SetL(mirror::CharArray::Alloc(self, 11));
434 ok = true;
435 } else if (caller == "java.lang.RealToString java.lang.RealToString.getInstance()") {
436 // Note: RealToString is implemented and used in a different fashion than IntegralToString.
437 // Conversion is done over an actual object of RealToString (the conversion method is an
438 // instance method). This means it is not as clear whether it is correct to return a new
439 // object each time. The caller needs to be inspected by hand to see whether it (incorrectly)
440 // stores the object for later use.
441 // See also b/19548084 for a possible rewrite and bringing it in line with IntegralToString.
442 if (shadow_frame->GetLink()->GetLink() != nullptr) {
443 std::string caller2(PrettyMethod(shadow_frame->GetLink()->GetLink()->GetMethod()));
444 if (caller2 == "java.lang.String java.lang.Double.toString(double)") {
445 // Allocate new object.
446 StackHandleScope<2> hs(self);
447 Handle<mirror::Class> h_real_to_string_class(hs.NewHandle(
448 shadow_frame->GetLink()->GetMethod()->GetDeclaringClass()));
449 Handle<mirror::Object> h_real_to_string_obj(hs.NewHandle(
450 h_real_to_string_class->AllocObject(self)));
451 if (h_real_to_string_obj.Get() != nullptr) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700452 auto* cl = Runtime::Current()->GetClassLinker();
453 ArtMethod* init_method = h_real_to_string_class->FindDirectMethod(
454 "<init>", "()V", cl->GetImagePointerSize());
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700455 if (init_method == nullptr) {
456 h_real_to_string_class->DumpClass(LOG(FATAL), mirror::Class::kDumpClassFullDetail);
457 } else {
458 JValue invoke_result;
459 EnterInterpreterFromInvoke(self, init_method, h_real_to_string_obj.Get(), nullptr,
460 nullptr);
461 if (!self->IsExceptionPending()) {
462 result->SetL(h_real_to_string_obj.Get());
463 ok = true;
464 }
465 }
466 }
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700467 }
468 }
469 }
470
471 if (!ok) {
Andreas Gampe068b0c02015-03-11 12:44:47 -0700472 AbortTransactionOrFail(self, "Could not create RealToString object");
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700473 }
474}
475
Andreas Gampe799681b2015-05-15 19:24:12 -0700476void UnstartedRuntime::UnstartedMathCeil(
Andreas Gampedd9d0552015-03-09 12:57:41 -0700477 Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700478 double in = shadow_frame->GetVRegDouble(arg_offset);
479 double out;
480 // Special cases:
481 // 1) NaN, infinity, +0, -0 -> out := in. All are guaranteed by cmath.
482 // -1 < in < 0 -> out := -0.
483 if (-1.0 < in && in < 0) {
484 out = -0.0;
485 } else {
486 out = ceil(in);
487 }
488 result->SetD(out);
489}
490
Andreas Gampe799681b2015-05-15 19:24:12 -0700491void UnstartedRuntime::UnstartedObjectHashCode(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700492 Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700493 mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset);
494 result->SetI(obj->IdentityHashCode());
495}
496
Andreas Gampe799681b2015-05-15 19:24:12 -0700497void UnstartedRuntime::UnstartedDoubleDoubleToRawLongBits(
Andreas Gampedd9d0552015-03-09 12:57:41 -0700498 Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700499 double in = shadow_frame->GetVRegDouble(arg_offset);
Roland Levillainda4d79b2015-03-24 14:36:11 +0000500 result->SetJ(bit_cast<int64_t, double>(in));
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700501}
502
Andreas Gampedd9d0552015-03-09 12:57:41 -0700503static mirror::Object* GetDexFromDexCache(Thread* self, mirror::DexCache* dex_cache)
Mathieu Chartier90443472015-07-16 20:32:27 -0700504 SHARED_REQUIRES(Locks::mutator_lock_) {
Andreas Gampedd9d0552015-03-09 12:57:41 -0700505 const DexFile* dex_file = dex_cache->GetDexFile();
506 if (dex_file == nullptr) {
507 return nullptr;
508 }
509
510 // Create the direct byte buffer.
511 JNIEnv* env = self->GetJniEnv();
512 DCHECK(env != nullptr);
513 void* address = const_cast<void*>(reinterpret_cast<const void*>(dex_file->Begin()));
Andreas Gampeaacc25d2015-04-01 14:49:06 -0700514 ScopedLocalRef<jobject> byte_buffer(env, env->NewDirectByteBuffer(address, dex_file->Size()));
515 if (byte_buffer.get() == nullptr) {
Andreas Gampedd9d0552015-03-09 12:57:41 -0700516 DCHECK(self->IsExceptionPending());
517 return nullptr;
518 }
519
520 jvalue args[1];
Andreas Gampeaacc25d2015-04-01 14:49:06 -0700521 args[0].l = byte_buffer.get();
522
523 ScopedLocalRef<jobject> dex(env, env->CallStaticObjectMethodA(
524 WellKnownClasses::com_android_dex_Dex,
525 WellKnownClasses::com_android_dex_Dex_create,
526 args));
527
528 return self->DecodeJObject(dex.get());
Andreas Gampedd9d0552015-03-09 12:57:41 -0700529}
530
Andreas Gampe799681b2015-05-15 19:24:12 -0700531void UnstartedRuntime::UnstartedDexCacheGetDexNative(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700532 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampedd9d0552015-03-09 12:57:41 -0700533 // We will create the Dex object, but the image writer will release it before creating the
534 // art file.
535 mirror::Object* src = shadow_frame->GetVRegReference(arg_offset);
536 bool have_dex = false;
537 if (src != nullptr) {
538 mirror::Object* dex = GetDexFromDexCache(self, reinterpret_cast<mirror::DexCache*>(src));
539 if (dex != nullptr) {
540 have_dex = true;
541 result->SetL(dex);
542 }
543 }
544 if (!have_dex) {
545 self->ClearException();
Sebastien Hertz2fd7e692015-04-02 11:11:19 +0200546 Runtime::Current()->AbortTransactionAndThrowAbortError(self, "Could not create Dex object");
Andreas Gampedd9d0552015-03-09 12:57:41 -0700547 }
548}
549
550static void UnstartedMemoryPeek(
551 Primitive::Type type, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
552 int64_t address = shadow_frame->GetVRegLong(arg_offset);
553 // TODO: Check that this is in the heap somewhere. Otherwise we will segfault instead of
554 // aborting the transaction.
555
556 switch (type) {
557 case Primitive::kPrimByte: {
558 result->SetB(*reinterpret_cast<int8_t*>(static_cast<intptr_t>(address)));
559 return;
560 }
561
562 case Primitive::kPrimShort: {
Andreas Gampe799681b2015-05-15 19:24:12 -0700563 typedef int16_t unaligned_short __attribute__ ((aligned (1)));
564 result->SetS(*reinterpret_cast<unaligned_short*>(static_cast<intptr_t>(address)));
Andreas Gampedd9d0552015-03-09 12:57:41 -0700565 return;
566 }
567
568 case Primitive::kPrimInt: {
Andreas Gampe799681b2015-05-15 19:24:12 -0700569 typedef int32_t unaligned_int __attribute__ ((aligned (1)));
570 result->SetI(*reinterpret_cast<unaligned_int*>(static_cast<intptr_t>(address)));
Andreas Gampedd9d0552015-03-09 12:57:41 -0700571 return;
572 }
573
574 case Primitive::kPrimLong: {
Andreas Gampe799681b2015-05-15 19:24:12 -0700575 typedef int64_t unaligned_long __attribute__ ((aligned (1)));
576 result->SetJ(*reinterpret_cast<unaligned_long*>(static_cast<intptr_t>(address)));
Andreas Gampedd9d0552015-03-09 12:57:41 -0700577 return;
578 }
579
580 case Primitive::kPrimBoolean:
581 case Primitive::kPrimChar:
582 case Primitive::kPrimFloat:
583 case Primitive::kPrimDouble:
584 case Primitive::kPrimVoid:
585 case Primitive::kPrimNot:
586 LOG(FATAL) << "Not in the Memory API: " << type;
587 UNREACHABLE();
588 }
589 LOG(FATAL) << "Should not reach here";
590 UNREACHABLE();
591}
592
Andreas Gampe799681b2015-05-15 19:24:12 -0700593void UnstartedRuntime::UnstartedMemoryPeekByte(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700594 Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe799681b2015-05-15 19:24:12 -0700595 UnstartedMemoryPeek(Primitive::kPrimByte, shadow_frame, result, arg_offset);
596}
597
598void UnstartedRuntime::UnstartedMemoryPeekShort(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700599 Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe799681b2015-05-15 19:24:12 -0700600 UnstartedMemoryPeek(Primitive::kPrimShort, shadow_frame, result, arg_offset);
601}
602
603void UnstartedRuntime::UnstartedMemoryPeekInt(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700604 Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe799681b2015-05-15 19:24:12 -0700605 UnstartedMemoryPeek(Primitive::kPrimInt, shadow_frame, result, arg_offset);
606}
607
608void UnstartedRuntime::UnstartedMemoryPeekLong(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700609 Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe799681b2015-05-15 19:24:12 -0700610 UnstartedMemoryPeek(Primitive::kPrimLong, shadow_frame, result, arg_offset);
Andreas Gampedd9d0552015-03-09 12:57:41 -0700611}
612
613static void UnstartedMemoryPeekArray(
614 Primitive::Type type, Thread* self, ShadowFrame* shadow_frame, size_t arg_offset)
Mathieu Chartier90443472015-07-16 20:32:27 -0700615 SHARED_REQUIRES(Locks::mutator_lock_) {
Andreas Gampedd9d0552015-03-09 12:57:41 -0700616 int64_t address_long = shadow_frame->GetVRegLong(arg_offset);
617 mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset + 2);
618 if (obj == nullptr) {
Sebastien Hertz2fd7e692015-04-02 11:11:19 +0200619 Runtime::Current()->AbortTransactionAndThrowAbortError(self, "Null pointer in peekArray");
Andreas Gampedd9d0552015-03-09 12:57:41 -0700620 return;
621 }
622 mirror::Array* array = obj->AsArray();
623
624 int offset = shadow_frame->GetVReg(arg_offset + 3);
625 int count = shadow_frame->GetVReg(arg_offset + 4);
626 if (offset < 0 || offset + count > array->GetLength()) {
627 std::string error_msg(StringPrintf("Array out of bounds in peekArray: %d/%d vs %d",
628 offset, count, array->GetLength()));
Sebastien Hertz2fd7e692015-04-02 11:11:19 +0200629 Runtime::Current()->AbortTransactionAndThrowAbortError(self, error_msg.c_str());
Andreas Gampedd9d0552015-03-09 12:57:41 -0700630 return;
631 }
632
633 switch (type) {
634 case Primitive::kPrimByte: {
635 int8_t* address = reinterpret_cast<int8_t*>(static_cast<intptr_t>(address_long));
636 mirror::ByteArray* byte_array = array->AsByteArray();
637 for (int32_t i = 0; i < count; ++i, ++address) {
638 byte_array->SetWithoutChecks<true>(i + offset, *address);
639 }
640 return;
641 }
642
643 case Primitive::kPrimShort:
644 case Primitive::kPrimInt:
645 case Primitive::kPrimLong:
646 LOG(FATAL) << "Type unimplemented for Memory Array API, should not reach here: " << type;
647 UNREACHABLE();
648
649 case Primitive::kPrimBoolean:
650 case Primitive::kPrimChar:
651 case Primitive::kPrimFloat:
652 case Primitive::kPrimDouble:
653 case Primitive::kPrimVoid:
654 case Primitive::kPrimNot:
655 LOG(FATAL) << "Not in the Memory API: " << type;
656 UNREACHABLE();
657 }
658 LOG(FATAL) << "Should not reach here";
659 UNREACHABLE();
660}
661
Andreas Gampe799681b2015-05-15 19:24:12 -0700662void UnstartedRuntime::UnstartedMemoryPeekByteArray(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700663 Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset) {
Andreas Gampe799681b2015-05-15 19:24:12 -0700664 UnstartedMemoryPeekArray(Primitive::kPrimByte, self, shadow_frame, arg_offset);
Andreas Gampedd9d0552015-03-09 12:57:41 -0700665}
666
Andreas Gampef778eb22015-04-13 14:17:09 -0700667// This allows reading security.properties in an unstarted runtime and initialize Security.
Andreas Gampe799681b2015-05-15 19:24:12 -0700668void UnstartedRuntime::UnstartedSecurityGetSecurityPropertiesReader(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700669 Thread* self, ShadowFrame* shadow_frame ATTRIBUTE_UNUSED, JValue* result,
670 size_t arg_offset ATTRIBUTE_UNUSED) {
Andreas Gampef778eb22015-04-13 14:17:09 -0700671 Runtime* runtime = Runtime::Current();
672 const std::vector<const DexFile*>& path = runtime->GetClassLinker()->GetBootClassPath();
673 std::string canonical(DexFile::GetDexCanonicalLocation(path[0]->GetLocation().c_str()));
674 mirror::String* string_data;
675
676 // Use a block to enclose the I/O and MemMap code so buffers are released early.
677 {
678 std::string error_msg;
679 std::unique_ptr<ZipArchive> zip_archive(ZipArchive::Open(canonical.c_str(), &error_msg));
680 if (zip_archive.get() == nullptr) {
681 AbortTransactionOrFail(self, "Could not open zip file %s: %s", canonical.c_str(),
682 error_msg.c_str());
683 return;
684 }
685 std::unique_ptr<ZipEntry> zip_entry(zip_archive->Find("java/security/security.properties",
686 &error_msg));
687 if (zip_entry.get() == nullptr) {
688 AbortTransactionOrFail(self, "Could not find security.properties file in %s: %s",
689 canonical.c_str(), error_msg.c_str());
690 return;
691 }
692 std::unique_ptr<MemMap> map(zip_entry->ExtractToMemMap(canonical.c_str(),
693 "java/security/security.properties",
694 &error_msg));
695 if (map.get() == nullptr) {
696 AbortTransactionOrFail(self, "Could not unzip security.properties file in %s: %s",
697 canonical.c_str(), error_msg.c_str());
698 return;
699 }
700
701 uint32_t length = zip_entry->GetUncompressedLength();
702 std::unique_ptr<char[]> tmp(new char[length + 1]);
703 memcpy(tmp.get(), map->Begin(), length);
704 tmp.get()[length] = 0; // null terminator
705
706 string_data = mirror::String::AllocFromModifiedUtf8(self, tmp.get());
707 }
708
709 if (string_data == nullptr) {
710 AbortTransactionOrFail(self, "Could not create string from file content of %s",
711 canonical.c_str());
712 return;
713 }
714
715 // Create a StringReader.
716 StackHandleScope<3> hs(self);
717 Handle<mirror::String> h_string(hs.NewHandle(string_data));
718
719 Handle<mirror::Class> h_class(hs.NewHandle(
720 runtime->GetClassLinker()->FindClass(self,
721 "Ljava/io/StringReader;",
Mathieu Chartier9865bde2015-12-21 09:58:16 -0800722 ScopedNullHandle<mirror::ClassLoader>())));
Andreas Gampef778eb22015-04-13 14:17:09 -0700723 if (h_class.Get() == nullptr) {
724 AbortTransactionOrFail(self, "Could not find StringReader class");
725 return;
726 }
727
728 if (!runtime->GetClassLinker()->EnsureInitialized(self, h_class, true, true)) {
729 AbortTransactionOrFail(self, "Could not initialize StringReader class");
730 return;
731 }
732
733 Handle<mirror::Object> h_obj(hs.NewHandle(h_class->AllocObject(self)));
734 if (h_obj.Get() == nullptr) {
735 AbortTransactionOrFail(self, "Could not allocate StringReader object");
736 return;
737 }
738
Mathieu Chartiere401d142015-04-22 13:56:20 -0700739 auto* cl = Runtime::Current()->GetClassLinker();
740 ArtMethod* constructor = h_class->FindDeclaredDirectMethod(
741 "<init>", "(Ljava/lang/String;)V", cl->GetImagePointerSize());
Andreas Gampef778eb22015-04-13 14:17:09 -0700742 if (constructor == nullptr) {
743 AbortTransactionOrFail(self, "Could not find StringReader constructor");
744 return;
745 }
746
747 uint32_t args[1];
748 args[0] = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(h_string.Get()));
749 EnterInterpreterFromInvoke(self, constructor, h_obj.Get(), args, nullptr);
750
751 if (self->IsExceptionPending()) {
752 AbortTransactionOrFail(self, "Could not run StringReader constructor");
753 return;
754 }
755
756 result->SetL(h_obj.Get());
757}
758
Kenny Root1c9e61c2015-05-14 15:58:17 -0700759// This allows reading the new style of String objects during compilation.
Andreas Gampe799681b2015-05-15 19:24:12 -0700760void UnstartedRuntime::UnstartedStringGetCharsNoCheck(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700761 Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset) {
Kenny Root1c9e61c2015-05-14 15:58:17 -0700762 jint start = shadow_frame->GetVReg(arg_offset + 1);
763 jint end = shadow_frame->GetVReg(arg_offset + 2);
764 jint index = shadow_frame->GetVReg(arg_offset + 4);
765 mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
766 if (string == nullptr) {
767 AbortTransactionOrFail(self, "String.getCharsNoCheck with null object");
768 return;
769 }
Kenny Root57f91e82015-05-14 15:58:17 -0700770 DCHECK_GE(start, 0);
771 DCHECK_GE(end, string->GetLength());
Kenny Root1c9e61c2015-05-14 15:58:17 -0700772 StackHandleScope<1> hs(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700773 Handle<mirror::CharArray> h_char_array(
774 hs.NewHandle(shadow_frame->GetVRegReference(arg_offset + 3)->AsCharArray()));
Kenny Root57f91e82015-05-14 15:58:17 -0700775 DCHECK_LE(index, h_char_array->GetLength());
776 DCHECK_LE(end - start, h_char_array->GetLength() - index);
Kenny Root1c9e61c2015-05-14 15:58:17 -0700777 string->GetChars(start, end, h_char_array, index);
778}
779
780// This allows reading chars from the new style of String objects during compilation.
Andreas Gampe799681b2015-05-15 19:24:12 -0700781void UnstartedRuntime::UnstartedStringCharAt(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700782 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Kenny Root1c9e61c2015-05-14 15:58:17 -0700783 jint index = shadow_frame->GetVReg(arg_offset + 1);
784 mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
785 if (string == nullptr) {
786 AbortTransactionOrFail(self, "String.charAt with null object");
787 return;
788 }
789 result->SetC(string->CharAt(index));
790}
791
Kenny Root57f91e82015-05-14 15:58:17 -0700792// This allows setting chars from the new style of String objects during compilation.
Andreas Gampe799681b2015-05-15 19:24:12 -0700793void UnstartedRuntime::UnstartedStringSetCharAt(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700794 Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset) {
Kenny Root57f91e82015-05-14 15:58:17 -0700795 jint index = shadow_frame->GetVReg(arg_offset + 1);
796 jchar c = shadow_frame->GetVReg(arg_offset + 2);
797 mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
798 if (string == nullptr) {
799 AbortTransactionOrFail(self, "String.setCharAt with null object");
800 return;
801 }
802 string->SetCharAt(index, c);
803}
804
Kenny Root1c9e61c2015-05-14 15:58:17 -0700805// This allows creating the new style of String objects during compilation.
Andreas Gampe799681b2015-05-15 19:24:12 -0700806void UnstartedRuntime::UnstartedStringFactoryNewStringFromChars(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700807 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Kenny Root1c9e61c2015-05-14 15:58:17 -0700808 jint offset = shadow_frame->GetVReg(arg_offset);
809 jint char_count = shadow_frame->GetVReg(arg_offset + 1);
810 DCHECK_GE(char_count, 0);
811 StackHandleScope<1> hs(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700812 Handle<mirror::CharArray> h_char_array(
813 hs.NewHandle(shadow_frame->GetVRegReference(arg_offset + 2)->AsCharArray()));
Kenny Root1c9e61c2015-05-14 15:58:17 -0700814 Runtime* runtime = Runtime::Current();
815 gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
816 result->SetL(mirror::String::AllocFromCharArray<true>(self, char_count, h_char_array, offset, allocator));
817}
818
819// This allows creating the new style of String objects during compilation.
Andreas Gampe799681b2015-05-15 19:24:12 -0700820void UnstartedRuntime::UnstartedStringFactoryNewStringFromString(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700821 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Kenny Root57f91e82015-05-14 15:58:17 -0700822 mirror::String* to_copy = shadow_frame->GetVRegReference(arg_offset)->AsString();
823 if (to_copy == nullptr) {
824 AbortTransactionOrFail(self, "StringFactory.newStringFromString with null object");
825 return;
826 }
827 StackHandleScope<1> hs(self);
828 Handle<mirror::String> h_string(hs.NewHandle(to_copy));
829 Runtime* runtime = Runtime::Current();
830 gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
831 result->SetL(mirror::String::AllocFromString<true>(self, h_string->GetLength(), h_string, 0,
832 allocator));
833}
834
Andreas Gampe799681b2015-05-15 19:24:12 -0700835void UnstartedRuntime::UnstartedStringFastSubstring(
Mathieu Chartiere401d142015-04-22 13:56:20 -0700836 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Kenny Root1c9e61c2015-05-14 15:58:17 -0700837 jint start = shadow_frame->GetVReg(arg_offset + 1);
838 jint length = shadow_frame->GetVReg(arg_offset + 2);
Kenny Root57f91e82015-05-14 15:58:17 -0700839 DCHECK_GE(start, 0);
Kenny Root1c9e61c2015-05-14 15:58:17 -0700840 DCHECK_GE(length, 0);
841 StackHandleScope<1> hs(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700842 Handle<mirror::String> h_string(
843 hs.NewHandle(shadow_frame->GetVRegReference(arg_offset)->AsString()));
Kenny Root57f91e82015-05-14 15:58:17 -0700844 DCHECK_LE(start, h_string->GetLength());
845 DCHECK_LE(start + length, h_string->GetLength());
Kenny Root1c9e61c2015-05-14 15:58:17 -0700846 Runtime* runtime = Runtime::Current();
847 gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
848 result->SetL(mirror::String::AllocFromString<true>(self, length, h_string, start, allocator));
849}
850
Kenny Root57f91e82015-05-14 15:58:17 -0700851// This allows getting the char array for new style of String objects during compilation.
Andreas Gampe799681b2015-05-15 19:24:12 -0700852void UnstartedRuntime::UnstartedStringToCharArray(
Kenny Root57f91e82015-05-14 15:58:17 -0700853 Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
Mathieu Chartier90443472015-07-16 20:32:27 -0700854 SHARED_REQUIRES(Locks::mutator_lock_) {
Kenny Root57f91e82015-05-14 15:58:17 -0700855 mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
856 if (string == nullptr) {
857 AbortTransactionOrFail(self, "String.charAt with null object");
858 return;
859 }
860 result->SetL(string->ToCharArray(self));
861}
862
Mathieu Chartiere401d142015-04-22 13:56:20 -0700863void UnstartedRuntime::UnstartedJNIVMRuntimeNewUnpaddedArray(
864 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
865 uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700866 int32_t length = args[1];
867 DCHECK_GE(length, 0);
868 mirror::Class* element_class = reinterpret_cast<mirror::Object*>(args[0])->AsClass();
869 Runtime* runtime = Runtime::Current();
870 mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(self, &element_class);
871 DCHECK(array_class != nullptr);
872 gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
873 result->SetL(mirror::Array::Alloc<true, true>(self, array_class, length,
874 array_class->GetComponentSizeShift(), allocator));
875}
876
Mathieu Chartiere401d142015-04-22 13:56:20 -0700877void UnstartedRuntime::UnstartedJNIVMStackGetCallingClassLoader(
878 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
879 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700880 result->SetL(nullptr);
881}
882
Mathieu Chartiere401d142015-04-22 13:56:20 -0700883void UnstartedRuntime::UnstartedJNIVMStackGetStackClass2(
884 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
885 uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700886 NthCallerVisitor visitor(self, 3);
887 visitor.WalkStack();
888 if (visitor.caller != nullptr) {
889 result->SetL(visitor.caller->GetDeclaringClass());
890 }
891}
892
Mathieu Chartiere401d142015-04-22 13:56:20 -0700893void UnstartedRuntime::UnstartedJNIMathLog(
894 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
895 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700896 JValue value;
897 value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
898 result->SetD(log(value.GetD()));
899}
900
Mathieu Chartiere401d142015-04-22 13:56:20 -0700901void UnstartedRuntime::UnstartedJNIMathExp(
902 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
903 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700904 JValue value;
905 value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
906 result->SetD(exp(value.GetD()));
907}
908
Mathieu Chartiere401d142015-04-22 13:56:20 -0700909void UnstartedRuntime::UnstartedJNIClassGetNameNative(
910 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver,
911 uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700912 StackHandleScope<1> hs(self);
913 result->SetL(mirror::Class::ComputeName(hs.NewHandle(receiver->AsClass())));
914}
915
Mathieu Chartiere401d142015-04-22 13:56:20 -0700916void UnstartedRuntime::UnstartedJNIFloatFloatToRawIntBits(
917 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
918 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700919 result->SetI(args[0]);
920}
921
Mathieu Chartiere401d142015-04-22 13:56:20 -0700922void UnstartedRuntime::UnstartedJNIFloatIntBitsToFloat(
923 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
924 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700925 result->SetI(args[0]);
926}
927
Mathieu Chartiere401d142015-04-22 13:56:20 -0700928void UnstartedRuntime::UnstartedJNIObjectInternalClone(
929 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver,
930 uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700931 result->SetL(receiver->Clone(self));
932}
933
Mathieu Chartiere401d142015-04-22 13:56:20 -0700934void UnstartedRuntime::UnstartedJNIObjectNotifyAll(
935 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver,
936 uint32_t* args ATTRIBUTE_UNUSED, JValue* result ATTRIBUTE_UNUSED) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700937 receiver->NotifyAll(self);
938}
939
Mathieu Chartiere401d142015-04-22 13:56:20 -0700940void UnstartedRuntime::UnstartedJNIStringCompareTo(
941 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver, uint32_t* args,
942 JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700943 mirror::String* rhs = reinterpret_cast<mirror::Object*>(args[0])->AsString();
944 if (rhs == nullptr) {
Andreas Gampe068b0c02015-03-11 12:44:47 -0700945 AbortTransactionOrFail(self, "String.compareTo with null object");
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700946 }
947 result->SetI(receiver->AsString()->CompareTo(rhs));
948}
949
Mathieu Chartiere401d142015-04-22 13:56:20 -0700950void UnstartedRuntime::UnstartedJNIStringIntern(
951 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver,
952 uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700953 result->SetL(receiver->AsString()->Intern());
954}
955
Mathieu Chartiere401d142015-04-22 13:56:20 -0700956void UnstartedRuntime::UnstartedJNIStringFastIndexOf(
957 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver,
958 uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700959 result->SetI(receiver->AsString()->FastIndexOf(args[0], args[1]));
960}
961
Mathieu Chartiere401d142015-04-22 13:56:20 -0700962void UnstartedRuntime::UnstartedJNIArrayCreateMultiArray(
963 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
964 uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700965 StackHandleScope<2> hs(self);
966 auto h_class(hs.NewHandle(reinterpret_cast<mirror::Class*>(args[0])->AsClass()));
967 auto h_dimensions(hs.NewHandle(reinterpret_cast<mirror::IntArray*>(args[1])->AsIntArray()));
968 result->SetL(mirror::Array::CreateMultiArray(self, h_class, h_dimensions));
969}
970
Mathieu Chartiere401d142015-04-22 13:56:20 -0700971void UnstartedRuntime::UnstartedJNIArrayCreateObjectArray(
972 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
973 uint32_t* args, JValue* result) {
Andreas Gampee598e042015-04-10 14:57:10 -0700974 int32_t length = static_cast<int32_t>(args[1]);
975 if (length < 0) {
976 ThrowNegativeArraySizeException(length);
977 return;
978 }
979 mirror::Class* element_class = reinterpret_cast<mirror::Class*>(args[0])->AsClass();
980 Runtime* runtime = Runtime::Current();
981 ClassLinker* class_linker = runtime->GetClassLinker();
982 mirror::Class* array_class = class_linker->FindArrayClass(self, &element_class);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700983 if (UNLIKELY(array_class == nullptr)) {
Andreas Gampee598e042015-04-10 14:57:10 -0700984 CHECK(self->IsExceptionPending());
985 return;
986 }
987 DCHECK(array_class->IsObjectArrayClass());
988 mirror::Array* new_array = mirror::ObjectArray<mirror::Object*>::Alloc(
989 self, array_class, length, runtime->GetHeap()->GetCurrentAllocator());
990 result->SetL(new_array);
991}
992
Mathieu Chartiere401d142015-04-22 13:56:20 -0700993void UnstartedRuntime::UnstartedJNIThrowableNativeFillInStackTrace(
994 Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
995 uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700996 ScopedObjectAccessUnchecked soa(self);
997 if (Runtime::Current()->IsActiveTransaction()) {
998 result->SetL(soa.Decode<mirror::Object*>(self->CreateInternalStackTrace<true>(soa)));
999 } else {
1000 result->SetL(soa.Decode<mirror::Object*>(self->CreateInternalStackTrace<false>(soa)));
1001 }
1002}
1003
Mathieu Chartiere401d142015-04-22 13:56:20 -07001004void UnstartedRuntime::UnstartedJNISystemIdentityHashCode(
1005 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1006 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001007 mirror::Object* obj = reinterpret_cast<mirror::Object*>(args[0]);
1008 result->SetI((obj != nullptr) ? obj->IdentityHashCode() : 0);
1009}
1010
Mathieu Chartiere401d142015-04-22 13:56:20 -07001011void UnstartedRuntime::UnstartedJNIByteOrderIsLittleEndian(
1012 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1013 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001014 result->SetZ(JNI_TRUE);
1015}
1016
Mathieu Chartiere401d142015-04-22 13:56:20 -07001017void UnstartedRuntime::UnstartedJNIUnsafeCompareAndSwapInt(
1018 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1019 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001020 mirror::Object* obj = reinterpret_cast<mirror::Object*>(args[0]);
1021 jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1];
1022 jint expectedValue = args[3];
1023 jint newValue = args[4];
1024 bool success;
1025 if (Runtime::Current()->IsActiveTransaction()) {
1026 success = obj->CasFieldStrongSequentiallyConsistent32<true>(MemberOffset(offset),
1027 expectedValue, newValue);
1028 } else {
1029 success = obj->CasFieldStrongSequentiallyConsistent32<false>(MemberOffset(offset),
1030 expectedValue, newValue);
1031 }
1032 result->SetZ(success ? JNI_TRUE : JNI_FALSE);
1033}
1034
Mathieu Chartiere401d142015-04-22 13:56:20 -07001035void UnstartedRuntime::UnstartedJNIUnsafePutObject(
1036 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1037 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result ATTRIBUTE_UNUSED) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001038 mirror::Object* obj = reinterpret_cast<mirror::Object*>(args[0]);
1039 jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1];
1040 mirror::Object* newValue = reinterpret_cast<mirror::Object*>(args[3]);
1041 if (Runtime::Current()->IsActiveTransaction()) {
1042 obj->SetFieldObject<true>(MemberOffset(offset), newValue);
1043 } else {
1044 obj->SetFieldObject<false>(MemberOffset(offset), newValue);
1045 }
1046}
1047
Andreas Gampe799681b2015-05-15 19:24:12 -07001048void UnstartedRuntime::UnstartedJNIUnsafeGetArrayBaseOffsetForComponentType(
Mathieu Chartiere401d142015-04-22 13:56:20 -07001049 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1050 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001051 mirror::Class* component = reinterpret_cast<mirror::Object*>(args[0])->AsClass();
1052 Primitive::Type primitive_type = component->GetPrimitiveType();
1053 result->SetI(mirror::Array::DataOffset(Primitive::ComponentSize(primitive_type)).Int32Value());
1054}
1055
Andreas Gampe799681b2015-05-15 19:24:12 -07001056void UnstartedRuntime::UnstartedJNIUnsafeGetArrayIndexScaleForComponentType(
Mathieu Chartiere401d142015-04-22 13:56:20 -07001057 Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
1058 mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001059 mirror::Class* component = reinterpret_cast<mirror::Object*>(args[0])->AsClass();
1060 Primitive::Type primitive_type = component->GetPrimitiveType();
1061 result->SetI(Primitive::ComponentSize(primitive_type));
1062}
1063
Andreas Gampedd9d0552015-03-09 12:57:41 -07001064typedef void (*InvokeHandler)(Thread* self, ShadowFrame* shadow_frame, JValue* result,
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001065 size_t arg_size);
1066
Mathieu Chartiere401d142015-04-22 13:56:20 -07001067typedef void (*JNIHandler)(Thread* self, ArtMethod* method, mirror::Object* receiver,
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001068 uint32_t* args, JValue* result);
1069
1070static bool tables_initialized_ = false;
1071static std::unordered_map<std::string, InvokeHandler> invoke_handlers_;
1072static std::unordered_map<std::string, JNIHandler> jni_handlers_;
1073
Andreas Gampe799681b2015-05-15 19:24:12 -07001074void UnstartedRuntime::InitializeInvokeHandlers() {
1075#define UNSTARTED_DIRECT(ShortName, Sig) \
1076 invoke_handlers_.insert(std::make_pair(Sig, & UnstartedRuntime::Unstarted ## ShortName));
1077#include "unstarted_runtime_list.h"
1078 UNSTARTED_RUNTIME_DIRECT_LIST(UNSTARTED_DIRECT)
1079#undef UNSTARTED_RUNTIME_DIRECT_LIST
1080#undef UNSTARTED_RUNTIME_JNI_LIST
1081#undef UNSTARTED_DIRECT
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001082}
1083
Andreas Gampe799681b2015-05-15 19:24:12 -07001084void UnstartedRuntime::InitializeJNIHandlers() {
1085#define UNSTARTED_JNI(ShortName, Sig) \
1086 jni_handlers_.insert(std::make_pair(Sig, & UnstartedRuntime::UnstartedJNI ## ShortName));
1087#include "unstarted_runtime_list.h"
1088 UNSTARTED_RUNTIME_JNI_LIST(UNSTARTED_JNI)
1089#undef UNSTARTED_RUNTIME_DIRECT_LIST
1090#undef UNSTARTED_RUNTIME_JNI_LIST
1091#undef UNSTARTED_JNI
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001092}
1093
Andreas Gampe799681b2015-05-15 19:24:12 -07001094void UnstartedRuntime::Initialize() {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001095 CHECK(!tables_initialized_);
1096
Andreas Gampe799681b2015-05-15 19:24:12 -07001097 InitializeInvokeHandlers();
1098 InitializeJNIHandlers();
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001099
1100 tables_initialized_ = true;
1101}
1102
Andreas Gampe799681b2015-05-15 19:24:12 -07001103void UnstartedRuntime::Invoke(Thread* self, const DexFile::CodeItem* code_item,
1104 ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001105 // In a runtime that's not started we intercept certain methods to avoid complicated dependency
1106 // problems in core libraries.
1107 CHECK(tables_initialized_);
1108
1109 std::string name(PrettyMethod(shadow_frame->GetMethod()));
1110 const auto& iter = invoke_handlers_.find(name);
1111 if (iter != invoke_handlers_.end()) {
Kenny Root57f91e82015-05-14 15:58:17 -07001112 // Clear out the result in case it's not zeroed out.
1113 result->SetL(0);
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001114 (*iter->second)(self, shadow_frame, result, arg_offset);
1115 } else {
1116 // Not special, continue with regular interpreter execution.
Andreas Gampe3cfa4d02015-10-06 17:04:01 -07001117 ArtInterpreterToInterpreterBridge(self, code_item, shadow_frame, result);
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001118 }
1119}
1120
1121// 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 -07001122void UnstartedRuntime::Jni(Thread* self, ArtMethod* method, mirror::Object* receiver,
Andreas Gampe799681b2015-05-15 19:24:12 -07001123 uint32_t* args, JValue* result) {
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001124 std::string name(PrettyMethod(method));
1125 const auto& iter = jni_handlers_.find(name);
1126 if (iter != jni_handlers_.end()) {
Kenny Root57f91e82015-05-14 15:58:17 -07001127 // Clear out the result in case it's not zeroed out.
1128 result->SetL(0);
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001129 (*iter->second)(self, method, receiver, args, result);
1130 } else if (Runtime::Current()->IsActiveTransaction()) {
Sebastien Hertz45b15972015-04-03 16:07:05 +02001131 AbortTransactionF(self, "Attempt to invoke native method in non-started runtime: %s",
1132 name.c_str());
Andreas Gampe2969bcd2015-03-09 12:57:41 -07001133 } else {
1134 LOG(FATAL) << "Calling native method " << PrettyMethod(method) << " in an unstarted "
1135 "non-transactional runtime";
1136 }
1137}
1138
1139} // namespace interpreter
1140} // namespace art