blob: 99ce1e2f4b2fc8df92a8759654db0f21f8c84adc [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
22#include "base/logging.h"
23#include "base/macros.h"
24#include "class_linker.h"
25#include "common_throws.h"
26#include "entrypoints/entrypoint_utils-inl.h"
27#include "handle_scope-inl.h"
28#include "interpreter/interpreter_common.h"
29#include "mirror/array-inl.h"
30#include "mirror/art_method-inl.h"
31#include "mirror/class.h"
32#include "mirror/object-inl.h"
33#include "mirror/object_array-inl.h"
34#include "mirror/string-inl.h"
35#include "nth_caller_visitor.h"
36#include "thread.h"
37#include "well_known_classes.h"
38
39namespace art {
40namespace interpreter {
41
42// Helper function to deal with class loading in an unstarted runtime.
43static void UnstartedRuntimeFindClass(Thread* self, Handle<mirror::String> className,
44 Handle<mirror::ClassLoader> class_loader, JValue* result,
45 const std::string& method_name, bool initialize_class,
46 bool abort_if_not_found)
47 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
48 CHECK(className.Get() != nullptr);
49 std::string descriptor(DotToDescriptor(className->ToModifiedUtf8().c_str()));
50 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
51
52 mirror::Class* found = class_linker->FindClass(self, descriptor.c_str(), class_loader);
53 if (found == nullptr && abort_if_not_found) {
54 if (!self->IsExceptionPending()) {
55 AbortTransaction(self, "%s failed in un-started runtime for class: %s",
56 method_name.c_str(), PrettyDescriptor(descriptor.c_str()).c_str());
57 }
58 return;
59 }
60 if (found != nullptr && initialize_class) {
61 StackHandleScope<1> hs(self);
62 Handle<mirror::Class> h_class(hs.NewHandle(found));
63 if (!class_linker->EnsureInitialized(self, h_class, true, true)) {
64 CHECK(self->IsExceptionPending());
65 return;
66 }
67 }
68 result->SetL(found);
69}
70
71// Common helper for class-loading cutouts in an unstarted runtime. We call Runtime methods that
72// rely on Java code to wrap errors in the correct exception class (i.e., NoClassDefFoundError into
73// ClassNotFoundException), so need to do the same. The only exception is if the exception is
74// actually InternalError. This must not be wrapped, as it signals an initialization abort.
75static void CheckExceptionGenerateClassNotFound(Thread* self)
76 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
77 if (self->IsExceptionPending()) {
78 // If it is not an InternalError, wrap it.
79 std::string type(PrettyTypeOf(self->GetException()));
80 if (type != "java.lang.InternalError") {
81 self->ThrowNewWrappedException("Ljava/lang/ClassNotFoundException;",
82 "ClassNotFoundException");
83 }
84 }
85}
86
87static void UnstartedClassForName(Thread* self, ShadowFrame* shadow_frame, JValue* result,
88 size_t arg_offset)
89 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
90 mirror::String* class_name = shadow_frame->GetVRegReference(arg_offset)->AsString();
91 StackHandleScope<1> hs(self);
92 Handle<mirror::String> h_class_name(hs.NewHandle(class_name));
93 UnstartedRuntimeFindClass(self, h_class_name, NullHandle<mirror::ClassLoader>(), result,
94 "Class.forName", true, false);
95 CheckExceptionGenerateClassNotFound(self);
96}
97
98static void UnstartedClassForNameLong(Thread* self, ShadowFrame* shadow_frame, JValue* result,
99 size_t arg_offset)
100 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
101 mirror::String* class_name = shadow_frame->GetVRegReference(arg_offset)->AsString();
102 bool initialize_class = shadow_frame->GetVReg(arg_offset + 1) != 0;
103 mirror::ClassLoader* class_loader =
104 down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset + 2));
105 StackHandleScope<2> hs(self);
106 Handle<mirror::String> h_class_name(hs.NewHandle(class_name));
107 Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(class_loader));
108 UnstartedRuntimeFindClass(self, h_class_name, h_class_loader, result, "Class.forName",
109 initialize_class, false);
110 CheckExceptionGenerateClassNotFound(self);
111}
112
113static void UnstartedClassClassForName(Thread* self, ShadowFrame* shadow_frame, JValue* result,
114 size_t arg_offset)
115 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
116 mirror::String* class_name = shadow_frame->GetVRegReference(arg_offset)->AsString();
117 bool initialize_class = shadow_frame->GetVReg(arg_offset + 1) != 0;
118 mirror::ClassLoader* class_loader =
119 down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset + 2));
120 StackHandleScope<2> hs(self);
121 Handle<mirror::String> h_class_name(hs.NewHandle(class_name));
122 Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(class_loader));
123 UnstartedRuntimeFindClass(self, h_class_name, h_class_loader, result, "Class.classForName",
124 initialize_class, false);
125 CheckExceptionGenerateClassNotFound(self);
126}
127
128static void UnstartedClassNewInstance(Thread* self, ShadowFrame* shadow_frame, JValue* result,
129 size_t arg_offset)
130 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
131 StackHandleScope<3> hs(self); // Class, constructor, object.
132 mirror::Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
133 Handle<mirror::Class> h_klass(hs.NewHandle(klass));
134 // There are two situations in which we'll abort this run.
135 // 1) If the class isn't yet initialized and initialization fails.
136 // 2) If we can't find the default constructor. We'll postpone the exception to runtime.
137 // Note that 2) could likely be handled here, but for safety abort the transaction.
138 bool ok = false;
139 if (Runtime::Current()->GetClassLinker()->EnsureInitialized(self, h_klass, true, true)) {
140 Handle<mirror::ArtMethod> h_cons(hs.NewHandle(
141 h_klass->FindDeclaredDirectMethod("<init>", "()V")));
142 if (h_cons.Get() != nullptr) {
143 Handle<mirror::Object> h_obj(hs.NewHandle(klass->AllocObject(self)));
144 CHECK(h_obj.Get() != nullptr); // We don't expect OOM at compile-time.
145 EnterInterpreterFromInvoke(self, h_cons.Get(), h_obj.Get(), nullptr, nullptr);
146 if (!self->IsExceptionPending()) {
147 result->SetL(h_obj.Get());
148 ok = true;
149 }
150 } else {
151 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
152 "Could not find default constructor for '%s'",
153 PrettyClass(h_klass.Get()).c_str());
154 }
155 }
156 if (!ok) {
157 std::string error_msg = StringPrintf("Failed in Class.newInstance for '%s' with %s",
158 PrettyClass(h_klass.Get()).c_str(),
159 PrettyTypeOf(self->GetException()).c_str());
160 Runtime::Current()->AbortTransactionAndThrowInternalError(self, error_msg);
161 }
162}
163
164static void UnstartedClassGetDeclaredField(Thread* self, ShadowFrame* shadow_frame, JValue* result,
165 size_t arg_offset)
166 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
167 // Special managed code cut-out to allow field lookup in a un-started runtime that'd fail
168 // going the reflective Dex way.
169 mirror::Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
170 mirror::String* name2 = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
171 mirror::ArtField* found = nullptr;
172 mirror::ObjectArray<mirror::ArtField>* fields = klass->GetIFields();
173 for (int32_t i = 0; i < fields->GetLength() && found == nullptr; ++i) {
174 mirror::ArtField* f = fields->Get(i);
175 if (name2->Equals(f->GetName())) {
176 found = f;
177 }
178 }
179 if (found == nullptr) {
180 fields = klass->GetSFields();
181 for (int32_t i = 0; i < fields->GetLength() && found == nullptr; ++i) {
182 mirror::ArtField* f = fields->Get(i);
183 if (name2->Equals(f->GetName())) {
184 found = f;
185 }
186 }
187 }
188 CHECK(found != nullptr)
189 << "Failed to find field in Class.getDeclaredField in un-started runtime. name="
190 << name2->ToModifiedUtf8() << " class=" << PrettyDescriptor(klass);
191 // TODO: getDeclaredField calls GetType once the field is found to ensure a
192 // NoClassDefFoundError is thrown if the field's type cannot be resolved.
193 mirror::Class* jlr_Field = self->DecodeJObject(
194 WellKnownClasses::java_lang_reflect_Field)->AsClass();
195 StackHandleScope<1> hs(self);
196 Handle<mirror::Object> field(hs.NewHandle(jlr_Field->AllocNonMovableObject(self)));
197 CHECK(field.Get() != nullptr);
198 mirror::ArtMethod* c = jlr_Field->FindDeclaredDirectMethod("<init>",
199 "(Ljava/lang/reflect/ArtField;)V");
200 uint32_t args[1];
201 args[0] = StackReference<mirror::Object>::FromMirrorPtr(found).AsVRegValue();
202 EnterInterpreterFromInvoke(self, c, field.Get(), args, nullptr);
203 result->SetL(field.Get());
204}
205
206static void UnstartedVmClassLoaderFindLoadedClass(Thread* self, ShadowFrame* shadow_frame,
207 JValue* result, size_t arg_offset)
208 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
209 mirror::String* class_name = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
210 mirror::ClassLoader* class_loader =
211 down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset));
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,
216 "VMClassLoader.findLoadedClass", false, false);
217 // This might have an error pending. But semantics are to just return null.
218 if (self->IsExceptionPending()) {
219 // If it is an InternalError, keep it. See CheckExceptionGenerateClassNotFound.
220 std::string type(PrettyTypeOf(self->GetException()));
221 if (type != "java.lang.InternalError") {
222 self->ClearException();
223 }
224 }
225}
226
227static void UnstartedVoidLookupType(Thread* self ATTRIBUTE_UNUSED,
228 ShadowFrame* shadow_frame ATTRIBUTE_UNUSED,
229 JValue* result,
230 size_t arg_offset ATTRIBUTE_UNUSED)
231 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
232 result->SetL(Runtime::Current()->GetClassLinker()->FindPrimitiveClass('V'));
233}
234
235static void UnstartedSystemArraycopy(Thread* self, ShadowFrame* shadow_frame,
236 JValue* result ATTRIBUTE_UNUSED, size_t arg_offset)
237 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
238 // Special case array copying without initializing System.
239 mirror::Class* ctype = shadow_frame->GetVRegReference(arg_offset)->GetClass()->GetComponentType();
240 jint srcPos = shadow_frame->GetVReg(arg_offset + 1);
241 jint dstPos = shadow_frame->GetVReg(arg_offset + 3);
242 jint length = shadow_frame->GetVReg(arg_offset + 4);
243 if (!ctype->IsPrimitive()) {
244 mirror::ObjectArray<mirror::Object>* src = shadow_frame->GetVRegReference(arg_offset)->
245 AsObjectArray<mirror::Object>();
246 mirror::ObjectArray<mirror::Object>* dst = shadow_frame->GetVRegReference(arg_offset + 2)->
247 AsObjectArray<mirror::Object>();
248 for (jint i = 0; i < length; ++i) {
249 dst->Set(dstPos + i, src->Get(srcPos + i));
250 }
251 } else if (ctype->IsPrimitiveChar()) {
252 mirror::CharArray* src = shadow_frame->GetVRegReference(arg_offset)->AsCharArray();
253 mirror::CharArray* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsCharArray();
254 for (jint i = 0; i < length; ++i) {
255 dst->Set(dstPos + i, src->Get(srcPos + i));
256 }
257 } else if (ctype->IsPrimitiveInt()) {
258 mirror::IntArray* src = shadow_frame->GetVRegReference(arg_offset)->AsIntArray();
259 mirror::IntArray* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsIntArray();
260 for (jint i = 0; i < length; ++i) {
261 dst->Set(dstPos + i, src->Get(srcPos + i));
262 }
263 } else {
264 std::string tmp = StringPrintf("Unimplemented System.arraycopy for type '%s'",
265 PrettyDescriptor(ctype).c_str());
266 Runtime::Current()->AbortTransactionAndThrowInternalError(self, tmp);
267 }
268}
269
270static void UnstartedThreadLocalGet(Thread* self, ShadowFrame* shadow_frame, JValue* result,
271 size_t arg_offset ATTRIBUTE_UNUSED)
272 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
273 std::string caller(PrettyMethod(shadow_frame->GetLink()->GetMethod()));
274 bool ok = false;
275 if (caller == "java.lang.String java.lang.IntegralToString.convertInt"
276 "(java.lang.AbstractStringBuilder, int)") {
277 // Allocate non-threadlocal buffer.
278 result->SetL(mirror::CharArray::Alloc(self, 11));
279 ok = true;
280 } else if (caller == "java.lang.RealToString java.lang.RealToString.getInstance()") {
281 // Note: RealToString is implemented and used in a different fashion than IntegralToString.
282 // Conversion is done over an actual object of RealToString (the conversion method is an
283 // instance method). This means it is not as clear whether it is correct to return a new
284 // object each time. The caller needs to be inspected by hand to see whether it (incorrectly)
285 // stores the object for later use.
286 // See also b/19548084 for a possible rewrite and bringing it in line with IntegralToString.
287 if (shadow_frame->GetLink()->GetLink() != nullptr) {
288 std::string caller2(PrettyMethod(shadow_frame->GetLink()->GetLink()->GetMethod()));
289 if (caller2 == "java.lang.String java.lang.Double.toString(double)") {
290 // Allocate new object.
291 StackHandleScope<2> hs(self);
292 Handle<mirror::Class> h_real_to_string_class(hs.NewHandle(
293 shadow_frame->GetLink()->GetMethod()->GetDeclaringClass()));
294 Handle<mirror::Object> h_real_to_string_obj(hs.NewHandle(
295 h_real_to_string_class->AllocObject(self)));
296 if (h_real_to_string_obj.Get() != nullptr) {
297 mirror::ArtMethod* init_method =
298 h_real_to_string_class->FindDirectMethod("<init>", "()V");
299 if (init_method == nullptr) {
300 h_real_to_string_class->DumpClass(LOG(FATAL), mirror::Class::kDumpClassFullDetail);
301 } else {
302 JValue invoke_result;
303 EnterInterpreterFromInvoke(self, init_method, h_real_to_string_obj.Get(), nullptr,
304 nullptr);
305 if (!self->IsExceptionPending()) {
306 result->SetL(h_real_to_string_obj.Get());
307 ok = true;
308 }
309 }
310 }
311
312 if (!ok) {
313 // We'll abort, so clear exception.
314 self->ClearException();
315 }
316 }
317 }
318 }
319
320 if (!ok) {
321 Runtime::Current()->AbortTransactionAndThrowInternalError(self,
322 "Could not create RealToString object");
323 }
324}
325
326static void UnstartedMathCeil(Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame,
327 JValue* result, size_t arg_offset) {
328 double in = shadow_frame->GetVRegDouble(arg_offset);
329 double out;
330 // Special cases:
331 // 1) NaN, infinity, +0, -0 -> out := in. All are guaranteed by cmath.
332 // -1 < in < 0 -> out := -0.
333 if (-1.0 < in && in < 0) {
334 out = -0.0;
335 } else {
336 out = ceil(in);
337 }
338 result->SetD(out);
339}
340
341static void UnstartedArtMethodGetMethodName(Thread* self, ShadowFrame* shadow_frame,
342 JValue* result, size_t arg_offset)
343 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
344 mirror::ArtMethod* method = shadow_frame->GetVRegReference(arg_offset)->AsArtMethod();
345 result->SetL(method->GetNameAsString(self));
346}
347
348static void UnstartedObjectHashCode(Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame,
349 JValue* result, size_t arg_offset)
350 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
351 mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset);
352 result->SetI(obj->IdentityHashCode());
353}
354
355static void UnstartedDoubleDoubleToRawLongBits(Thread* self ATTRIBUTE_UNUSED,
356 ShadowFrame* shadow_frame, JValue* result,
357 size_t arg_offset) {
358 double in = shadow_frame->GetVRegDouble(arg_offset);
359 result->SetJ(bit_cast<int64_t>(in));
360}
361
362static void UnstartedJNIVMRuntimeNewUnpaddedArray(Thread* self,
363 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
364 mirror::Object* receiver ATTRIBUTE_UNUSED,
365 uint32_t* args,
366 JValue* result)
367 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
368 int32_t length = args[1];
369 DCHECK_GE(length, 0);
370 mirror::Class* element_class = reinterpret_cast<mirror::Object*>(args[0])->AsClass();
371 Runtime* runtime = Runtime::Current();
372 mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(self, &element_class);
373 DCHECK(array_class != nullptr);
374 gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
375 result->SetL(mirror::Array::Alloc<true, true>(self, array_class, length,
376 array_class->GetComponentSizeShift(), allocator));
377}
378
379static void UnstartedJNIVMStackGetCallingClassLoader(Thread* self ATTRIBUTE_UNUSED,
380 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
381 mirror::Object* receiver ATTRIBUTE_UNUSED,
382 uint32_t* args ATTRIBUTE_UNUSED,
383 JValue* result) {
384 result->SetL(nullptr);
385}
386
387static void UnstartedJNIVMStackGetStackClass2(Thread* self,
388 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
389 mirror::Object* receiver ATTRIBUTE_UNUSED,
390 uint32_t* args ATTRIBUTE_UNUSED,
391 JValue* result)
392 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
393 NthCallerVisitor visitor(self, 3);
394 visitor.WalkStack();
395 if (visitor.caller != nullptr) {
396 result->SetL(visitor.caller->GetDeclaringClass());
397 }
398}
399
400static void UnstartedJNIMathLog(Thread* self ATTRIBUTE_UNUSED,
401 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
402 mirror::Object* receiver ATTRIBUTE_UNUSED,
403 uint32_t* args,
404 JValue* result) {
405 JValue value;
406 value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
407 result->SetD(log(value.GetD()));
408}
409
410static void UnstartedJNIMathExp(Thread* self ATTRIBUTE_UNUSED,
411 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
412 mirror::Object* receiver ATTRIBUTE_UNUSED,
413 uint32_t* args,
414 JValue* result) {
415 JValue value;
416 value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
417 result->SetD(exp(value.GetD()));
418}
419
420static void UnstartedJNIClassGetNameNative(Thread* self,
421 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
422 mirror::Object* receiver,
423 uint32_t* args ATTRIBUTE_UNUSED,
424 JValue* result)
425 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
426 StackHandleScope<1> hs(self);
427 result->SetL(mirror::Class::ComputeName(hs.NewHandle(receiver->AsClass())));
428}
429
430static void UnstartedJNIFloatFloatToRawIntBits(Thread* self ATTRIBUTE_UNUSED,
431 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
432 mirror::Object* receiver ATTRIBUTE_UNUSED,
433 uint32_t* args,
434 JValue* result) {
435 result->SetI(args[0]);
436}
437
438static void UnstartedJNIFloatIntBitsToFloat(Thread* self ATTRIBUTE_UNUSED,
439 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
440 mirror::Object* receiver ATTRIBUTE_UNUSED,
441 uint32_t* args,
442 JValue* result) {
443 result->SetI(args[0]);
444}
445
446static void UnstartedJNIObjectInternalClone(Thread* self ATTRIBUTE_UNUSED,
447 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
448 mirror::Object* receiver,
449 uint32_t* args ATTRIBUTE_UNUSED,
450 JValue* result)
451 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
452 result->SetL(receiver->Clone(self));
453}
454
455static void UnstartedJNIObjectNotifyAll(Thread* self ATTRIBUTE_UNUSED,
456 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
457 mirror::Object* receiver,
458 uint32_t* args ATTRIBUTE_UNUSED,
459 JValue* result ATTRIBUTE_UNUSED)
460 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
461 receiver->NotifyAll(self);
462}
463
464static void UnstartedJNIStringCompareTo(Thread* self,
465 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
466 mirror::Object* receiver,
467 uint32_t* args,
468 JValue* result)
469 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
470 mirror::String* rhs = reinterpret_cast<mirror::Object*>(args[0])->AsString();
471 if (rhs == nullptr) {
472 AbortTransaction(self, "String.compareTo with null object");
473 }
474 result->SetI(receiver->AsString()->CompareTo(rhs));
475}
476
477static void UnstartedJNIStringIntern(Thread* self ATTRIBUTE_UNUSED,
478 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
479 mirror::Object* receiver,
480 uint32_t* args ATTRIBUTE_UNUSED,
481 JValue* result)
482 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
483 result->SetL(receiver->AsString()->Intern());
484}
485
486static void UnstartedJNIStringFastIndexOf(Thread* self ATTRIBUTE_UNUSED,
487 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
488 mirror::Object* receiver,
489 uint32_t* args,
490 JValue* result)
491 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
492 result->SetI(receiver->AsString()->FastIndexOf(args[0], args[1]));
493}
494
495static void UnstartedJNIArrayCreateMultiArray(Thread* self,
496 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
497 mirror::Object* receiver ATTRIBUTE_UNUSED,
498 uint32_t* args,
499 JValue* result)
500 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
501 StackHandleScope<2> hs(self);
502 auto h_class(hs.NewHandle(reinterpret_cast<mirror::Class*>(args[0])->AsClass()));
503 auto h_dimensions(hs.NewHandle(reinterpret_cast<mirror::IntArray*>(args[1])->AsIntArray()));
504 result->SetL(mirror::Array::CreateMultiArray(self, h_class, h_dimensions));
505}
506
507static void UnstartedJNIThrowableNativeFillInStackTrace(Thread* self,
508 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
509 mirror::Object* receiver ATTRIBUTE_UNUSED,
510 uint32_t* args ATTRIBUTE_UNUSED,
511 JValue* result)
512 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
513 ScopedObjectAccessUnchecked soa(self);
514 if (Runtime::Current()->IsActiveTransaction()) {
515 result->SetL(soa.Decode<mirror::Object*>(self->CreateInternalStackTrace<true>(soa)));
516 } else {
517 result->SetL(soa.Decode<mirror::Object*>(self->CreateInternalStackTrace<false>(soa)));
518 }
519}
520
521static void UnstartedJNISystemIdentityHashCode(Thread* self ATTRIBUTE_UNUSED,
522 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
523 mirror::Object* receiver ATTRIBUTE_UNUSED,
524 uint32_t* args,
525 JValue* result)
526 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
527 mirror::Object* obj = reinterpret_cast<mirror::Object*>(args[0]);
528 result->SetI((obj != nullptr) ? obj->IdentityHashCode() : 0);
529}
530
531static void UnstartedJNIByteOrderIsLittleEndian(Thread* self ATTRIBUTE_UNUSED,
532 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
533 mirror::Object* receiver ATTRIBUTE_UNUSED,
534 uint32_t* args ATTRIBUTE_UNUSED,
535 JValue* result) {
536 result->SetZ(JNI_TRUE);
537}
538
539static void UnstartedJNIUnsafeCompareAndSwapInt(Thread* self ATTRIBUTE_UNUSED,
540 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
541 mirror::Object* receiver ATTRIBUTE_UNUSED,
542 uint32_t* args,
543 JValue* result)
544 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
545 mirror::Object* obj = reinterpret_cast<mirror::Object*>(args[0]);
546 jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1];
547 jint expectedValue = args[3];
548 jint newValue = args[4];
549 bool success;
550 if (Runtime::Current()->IsActiveTransaction()) {
551 success = obj->CasFieldStrongSequentiallyConsistent32<true>(MemberOffset(offset),
552 expectedValue, newValue);
553 } else {
554 success = obj->CasFieldStrongSequentiallyConsistent32<false>(MemberOffset(offset),
555 expectedValue, newValue);
556 }
557 result->SetZ(success ? JNI_TRUE : JNI_FALSE);
558}
559
560static void UnstartedJNIUnsafePutObject(Thread* self ATTRIBUTE_UNUSED,
561 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
562 mirror::Object* receiver ATTRIBUTE_UNUSED,
563 uint32_t* args,
564 JValue* result ATTRIBUTE_UNUSED)
565 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
566 mirror::Object* obj = reinterpret_cast<mirror::Object*>(args[0]);
567 jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1];
568 mirror::Object* newValue = reinterpret_cast<mirror::Object*>(args[3]);
569 if (Runtime::Current()->IsActiveTransaction()) {
570 obj->SetFieldObject<true>(MemberOffset(offset), newValue);
571 } else {
572 obj->SetFieldObject<false>(MemberOffset(offset), newValue);
573 }
574}
575
576static void UnstartedJNIUnsafeGetArrayBaseOffsetForComponentType(
577 Thread* self ATTRIBUTE_UNUSED,
578 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
579 mirror::Object* receiver ATTRIBUTE_UNUSED,
580 uint32_t* args,
581 JValue* result)
582 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
583 mirror::Class* component = reinterpret_cast<mirror::Object*>(args[0])->AsClass();
584 Primitive::Type primitive_type = component->GetPrimitiveType();
585 result->SetI(mirror::Array::DataOffset(Primitive::ComponentSize(primitive_type)).Int32Value());
586}
587
588static void UnstartedJNIUnsafeGetArrayIndexScaleForComponentType(
589 Thread* self ATTRIBUTE_UNUSED,
590 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
591 mirror::Object* receiver ATTRIBUTE_UNUSED,
592 uint32_t* args,
593 JValue* result)
594 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
595 mirror::Class* component = reinterpret_cast<mirror::Object*>(args[0])->AsClass();
596 Primitive::Type primitive_type = component->GetPrimitiveType();
597 result->SetI(Primitive::ComponentSize(primitive_type));
598}
599
600typedef void(*InvokeHandler)(Thread* self, ShadowFrame* shadow_frame, JValue* result,
601 size_t arg_size);
602
603typedef void(*JNIHandler)(Thread* self, mirror::ArtMethod* method, mirror::Object* receiver,
604 uint32_t* args, JValue* result);
605
606static bool tables_initialized_ = false;
607static std::unordered_map<std::string, InvokeHandler> invoke_handlers_;
608static std::unordered_map<std::string, JNIHandler> jni_handlers_;
609
610static void UnstartedRuntimeInitializeInvokeHandlers() {
611 struct InvokeHandlerDef {
612 std::string name;
613 InvokeHandler function;
614 };
615
616 InvokeHandlerDef defs[] {
617 { "java.lang.Class java.lang.Class.forName(java.lang.String)",
618 &UnstartedClassForName },
619 { "java.lang.Class java.lang.Class.forName(java.lang.String, boolean, java.lang.ClassLoader)",
620 &UnstartedClassForNameLong },
621 { "java.lang.Class java.lang.Class.classForName(java.lang.String, boolean, java.lang.ClassLoader)",
622 &UnstartedClassClassForName },
623 { "java.lang.Class java.lang.VMClassLoader.findLoadedClass(java.lang.ClassLoader, java.lang.String)",
624 &UnstartedVmClassLoaderFindLoadedClass },
625 { "java.lang.Class java.lang.Void.lookupType()",
626 &UnstartedVoidLookupType },
627 { "java.lang.Object java.lang.Class.newInstance()",
628 &UnstartedClassNewInstance },
629 { "java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String)",
630 &UnstartedClassGetDeclaredField },
631 { "int java.lang.Object.hashCode()",
632 &UnstartedObjectHashCode },
633 { "java.lang.String java.lang.reflect.ArtMethod.getMethodName(java.lang.reflect.ArtMethod)",
634 &UnstartedArtMethodGetMethodName },
635 { "void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int)",
636 &UnstartedSystemArraycopy},
637 { "void java.lang.System.arraycopy(char[], int, char[], int, int)",
638 &UnstartedSystemArraycopy },
639 { "void java.lang.System.arraycopy(int[], int, int[], int, int)",
640 &UnstartedSystemArraycopy },
641 { "long java.lang.Double.doubleToRawLongBits(double)",
642 &UnstartedDoubleDoubleToRawLongBits },
643 { "double java.lang.Math.ceil(double)",
644 &UnstartedMathCeil },
645 { "java.lang.Object java.lang.ThreadLocal.get()",
646 &UnstartedThreadLocalGet },
647 };
648
649 for (auto& def : defs) {
650 invoke_handlers_.insert(std::make_pair(def.name, def.function));
651 }
652}
653
654static void UnstartedRuntimeInitializeJNIHandlers() {
655 struct JNIHandlerDef {
656 std::string name;
657 JNIHandler function;
658 };
659
660 JNIHandlerDef defs[] {
661 { "java.lang.Object dalvik.system.VMRuntime.newUnpaddedArray(java.lang.Class, int)",
662 &UnstartedJNIVMRuntimeNewUnpaddedArray },
663 { "java.lang.ClassLoader dalvik.system.VMStack.getCallingClassLoader()",
664 &UnstartedJNIVMStackGetCallingClassLoader },
665 { "java.lang.Class dalvik.system.VMStack.getStackClass2()",
666 &UnstartedJNIVMStackGetStackClass2 },
667 { "double java.lang.Math.log(double)",
668 &UnstartedJNIMathLog },
669 { "java.lang.String java.lang.Class.getNameNative()",
670 &UnstartedJNIClassGetNameNative },
671 { "int java.lang.Float.floatToRawIntBits(float)",
672 &UnstartedJNIFloatFloatToRawIntBits },
673 { "float java.lang.Float.intBitsToFloat(int)",
674 &UnstartedJNIFloatIntBitsToFloat },
675 { "double java.lang.Math.exp(double)",
676 &UnstartedJNIMathExp },
677 { "java.lang.Object java.lang.Object.internalClone()",
678 &UnstartedJNIObjectInternalClone },
679 { "void java.lang.Object.notifyAll()",
680 &UnstartedJNIObjectNotifyAll},
681 { "int java.lang.String.compareTo(java.lang.String)",
682 &UnstartedJNIStringCompareTo },
683 { "java.lang.String java.lang.String.intern()",
684 &UnstartedJNIStringIntern },
685 { "int java.lang.String.fastIndexOf(int, int)",
686 &UnstartedJNIStringFastIndexOf },
687 { "java.lang.Object java.lang.reflect.Array.createMultiArray(java.lang.Class, int[])",
688 &UnstartedJNIArrayCreateMultiArray },
689 { "java.lang.Object java.lang.Throwable.nativeFillInStackTrace()",
690 &UnstartedJNIThrowableNativeFillInStackTrace },
691 { "int java.lang.System.identityHashCode(java.lang.Object)",
692 &UnstartedJNISystemIdentityHashCode },
693 { "boolean java.nio.ByteOrder.isLittleEndian()",
694 &UnstartedJNIByteOrderIsLittleEndian },
695 { "boolean sun.misc.Unsafe.compareAndSwapInt(java.lang.Object, long, int, int)",
696 &UnstartedJNIUnsafeCompareAndSwapInt },
697 { "void sun.misc.Unsafe.putObject(java.lang.Object, long, java.lang.Object)",
698 &UnstartedJNIUnsafePutObject },
699 { "int sun.misc.Unsafe.getArrayBaseOffsetForComponentType(java.lang.Class)",
700 &UnstartedJNIUnsafeGetArrayBaseOffsetForComponentType },
701 { "int sun.misc.Unsafe.getArrayIndexScaleForComponentType(java.lang.Class)",
702 &UnstartedJNIUnsafeGetArrayIndexScaleForComponentType },
703 };
704
705 for (auto& def : defs) {
706 jni_handlers_.insert(std::make_pair(def.name, def.function));
707 }
708}
709
710void UnstartedRuntimeInitialize() {
711 CHECK(!tables_initialized_);
712
713 UnstartedRuntimeInitializeInvokeHandlers();
714 UnstartedRuntimeInitializeJNIHandlers();
715
716 tables_initialized_ = true;
717}
718
719void UnstartedRuntimeInvoke(Thread* self, const DexFile::CodeItem* code_item,
720 ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
721 // In a runtime that's not started we intercept certain methods to avoid complicated dependency
722 // problems in core libraries.
723 CHECK(tables_initialized_);
724
725 std::string name(PrettyMethod(shadow_frame->GetMethod()));
726 const auto& iter = invoke_handlers_.find(name);
727 if (iter != invoke_handlers_.end()) {
728 (*iter->second)(self, shadow_frame, result, arg_offset);
729 } else {
730 // Not special, continue with regular interpreter execution.
731 artInterpreterToInterpreterBridge(self, code_item, shadow_frame, result);
732 }
733}
734
735// Hand select a number of methods to be run in a not yet started runtime without using JNI.
736void UnstartedRuntimeJni(Thread* self, mirror::ArtMethod* method, mirror::Object* receiver,
737 uint32_t* args, JValue* result) {
738 std::string name(PrettyMethod(method));
739 const auto& iter = jni_handlers_.find(name);
740 if (iter != jni_handlers_.end()) {
741 (*iter->second)(self, method, receiver, args, result);
742 } else if (Runtime::Current()->IsActiveTransaction()) {
743 AbortTransaction(self, "Attempt to invoke native method in non-started runtime: %s",
744 name.c_str());
745 } else {
746 LOG(FATAL) << "Calling native method " << PrettyMethod(method) << " in an unstarted "
747 "non-transactional runtime";
748 }
749}
750
751} // namespace interpreter
752} // namespace art