diff options
Diffstat (limited to 'runtime')
| -rw-r--r-- | runtime/arch/arm/quick_entrypoints_arm.S | 26 | ||||
| -rw-r--r-- | runtime/arch/arm64/quick_entrypoints_arm64.S | 25 | ||||
| -rw-r--r-- | runtime/arch/mips/quick_entrypoints_mips.S | 23 | ||||
| -rw-r--r-- | runtime/arch/mips64/quick_entrypoints_mips64.S | 86 | ||||
| -rw-r--r-- | runtime/arch/x86/quick_entrypoints_x86.S | 8 | ||||
| -rw-r--r-- | runtime/arch/x86_64/quick_entrypoints_x86_64.S | 8 | ||||
| -rw-r--r-- | runtime/barrier.cc | 2 | ||||
| -rw-r--r-- | runtime/entrypoints/entrypoint_utils-inl.h | 24 | ||||
| -rw-r--r-- | runtime/entrypoints/quick/quick_default_externs.h | 8 | ||||
| -rw-r--r-- | runtime/entrypoints/quick/quick_dexcache_entrypoints.cc | 16 | ||||
| -rw-r--r-- | runtime/entrypoints/quick/quick_entrypoints_list.h | 8 | ||||
| -rw-r--r-- | runtime/native/dalvik_system_ZygoteHooks.cc | 7 | ||||
| -rw-r--r-- | runtime/reflection.cc | 12 | ||||
| -rw-r--r-- | runtime/stack.cc | 64 | ||||
| -rw-r--r-- | runtime/stack.h | 6 | ||||
| -rw-r--r-- | runtime/thread.cc | 21 | ||||
| -rw-r--r-- | runtime/thread.h | 1 | ||||
| -rw-r--r-- | runtime/utils_test.cc | 3 | ||||
| -rw-r--r-- | runtime/well_known_classes.cc | 2 | ||||
| -rw-r--r-- | runtime/well_known_classes.h | 1 |
20 files changed, 173 insertions, 178 deletions
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S index 8f6162ffa0..599c22a088 100644 --- a/runtime/arch/arm/quick_entrypoints_arm.S +++ b/runtime/arch/arm/quick_entrypoints_arm.S @@ -669,6 +669,18 @@ ENTRY art_quick_aput_obj END art_quick_aput_obj // Macro to facilitate adding new allocation entrypoints. +.macro ONE_ARG_DOWNCALL name, entrypoint, return + .extern \entrypoint +ENTRY \name + SETUP_REFS_ONLY_CALLEE_SAVE_FRAME r1, r2 @ save callee saves in case of GC + mov r1, r9 @ pass Thread::Current + bl \entrypoint @ (uint32_t type_idx, Method* method, Thread*) + RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME + \return +END \name +.endm + +// Macro to facilitate adding new allocation entrypoints. .macro TWO_ARG_DOWNCALL name, entrypoint, return .extern \entrypoint ENTRY \name @@ -693,10 +705,9 @@ ENTRY \name END \name .endm -TWO_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER - -TWO_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER -TWO_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER +ONE_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER +ONE_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER +ONE_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER /* * Called by managed code to resolve a static field and load a non-wide value. @@ -805,11 +816,10 @@ END art_quick_set64_instance /* * Entry from managed code to resolve a string, this stub will allocate a String and deliver an - * exception on error. On success the String is returned. R0 holds the referring method, - * R1 holds the string index. The fast path check for hit in strings cache has already been - * performed. + * exception on error. On success the String is returned. R0 holds the string index. The fast + * path check for hit in strings cache has already been performed. */ -TWO_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER +ONE_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER // Generate the allocation entrypoints for each allocator. GENERATE_ALL_ALLOC_ENTRYPOINTS diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S index cbd4b7c337..1e78877de7 100644 --- a/runtime/arch/arm64/quick_entrypoints_arm64.S +++ b/runtime/arch/arm64/quick_entrypoints_arm64.S @@ -1261,6 +1261,18 @@ ENTRY art_quick_aput_obj END art_quick_aput_obj // Macro to facilitate adding new allocation entrypoints. +.macro ONE_ARG_DOWNCALL name, entrypoint, return + .extern \entrypoint +ENTRY \name + SETUP_REFS_ONLY_CALLEE_SAVE_FRAME // save callee saves in case of GC + mov x1, xSELF // pass Thread::Current + bl \entrypoint // (uint32_t type_idx, Method* method, Thread*) + RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME + \return +END \name +.endm + +// Macro to facilitate adding new allocation entrypoints. .macro TWO_ARG_DOWNCALL name, entrypoint, return .extern \entrypoint ENTRY \name @@ -1339,10 +1351,10 @@ TWO_ARG_REF_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, * initializer and deliver the exception on error. On success the static storage base is * returned. */ -TWO_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER +ONE_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER -TWO_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER -TWO_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER +ONE_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER +ONE_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER ONE_ARG_REF_DOWNCALL art_quick_get_boolean_static, artGetBooleanStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1 ONE_ARG_REF_DOWNCALL art_quick_get_byte_static, artGetByteStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1 @@ -1386,11 +1398,10 @@ END art_quick_set64_static /* * Entry from managed code to resolve a string, this stub will allocate a String and deliver an - * exception on error. On success the String is returned. x0 holds the referring method, - * w1 holds the string index. The fast path check for hit in strings cache has already been - * performed. + * exception on error. On success the String is returned. w0 holds the string index. The fast + * path check for hit in strings cache has already been performed. */ -TWO_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER +ONE_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER // Generate the allocation entrypoints for each allocator. GENERATE_ALL_ALLOC_ENTRYPOINTS diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S index 622c48f55f..356a145eae 100644 --- a/runtime/arch/mips/quick_entrypoints_mips.S +++ b/runtime/arch/mips/quick_entrypoints_mips.S @@ -982,6 +982,16 @@ ENTRY art_quick_set_obj_instance RETURN_IF_ZERO END art_quick_set_obj_instance +.macro ONE_ARG_DOWNCALL name, entrypoint, return + .extern \entrypoint +ENTRY \name + SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC + jal \entrypoint + move $a1, rSELF # pass Thread::Current + \return +END \name +.endm + // Macro to facilitate adding new allocation entrypoints. .macro TWO_ARG_DOWNCALL name, entrypoint, return .extern \entrypoint @@ -1008,29 +1018,28 @@ GENERATE_ALL_ALLOC_ENTRYPOINTS /* * Entry from managed code to resolve a string, this stub will allocate a String and deliver an - * exception on error. On success the String is returned. R0 holds the referring method, - * R1 holds the string index. The fast path check for hit in strings cache has already been - * performed. + * exception on error. On success the String is returned. A0 holds the string index. The fast + * path check for hit in strings cache has already been performed. */ -TWO_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER +ONE_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER /* * Entry from managed code when uninitialized static storage, this stub will run the class * initializer and deliver the exception on error. On success the static storage base is * returned. */ -TWO_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER +ONE_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER /* * Entry from managed code when dex cache misses for a type_idx. */ -TWO_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER +ONE_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER /* * Entry from managed code when type_idx needs to be checked for access and dex cache may also * miss. */ -TWO_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER +ONE_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER /* * Called by managed code when the value in rSUSPEND has been decremented to 0. diff --git a/runtime/arch/mips64/quick_entrypoints_mips64.S b/runtime/arch/mips64/quick_entrypoints_mips64.S index bf18dd5f82..f867aa8367 100644 --- a/runtime/arch/mips64/quick_entrypoints_mips64.S +++ b/runtime/arch/mips64/quick_entrypoints_mips64.S @@ -945,45 +945,6 @@ ENTRY art_quick_aput_obj END art_quick_aput_obj /* - * Entry from managed code when uninitialized static storage, this stub will run the class - * initializer and deliver the exception on error. On success the static storage base is - * returned. - */ - .extern artInitializeStaticStorageFromCode -ENTRY art_quick_initialize_static_storage - SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC - # artInitializeStaticStorageFromCode(uint32_t type_idx, Method* referrer, Thread*) - jal artInitializeStaticStorageFromCode - move $a2, rSELF # pass Thread::Current - RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER -END art_quick_initialize_static_storage - - /* - * Entry from managed code when dex cache misses for a type_idx. - */ - .extern artInitializeTypeFromCode -ENTRY art_quick_initialize_type - SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC - # artInitializeTypeFromCode(uint32_t type_idx, Method* referrer, Thread*) - jal artInitializeTypeFromCode - move $a2, rSELF # pass Thread::Current - RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER -END art_quick_initialize_type - - /* - * Entry from managed code when type_idx needs to be checked for access and dex cache may also - * miss. - */ - .extern artInitializeTypeAndVerifyAccessFromCode -ENTRY art_quick_initialize_type_and_verify_access - SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC - # artInitializeTypeFromCode(uint32_t type_idx, Method* referrer, Thread*) - jal artInitializeTypeAndVerifyAccessFromCode - move $a2, rSELF # pass Thread::Current - RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER -END art_quick_initialize_type_and_verify_access - - /* * Called by managed code to resolve a static field and load a boolean primitive value. */ .extern artGetBooleanStaticFromCode @@ -1272,20 +1233,16 @@ ENTRY art_quick_set_obj_instance RETURN_IF_ZERO END art_quick_set_obj_instance - /* - * Entry from managed code to resolve a string, this stub will allocate a String and deliver an - * exception on error. On success the String is returned. R0 holds the referring method, - * R1 holds the string index. The fast path check for hit in strings cache has already been - * performed. - */ - .extern artResolveStringFromCode -ENTRY art_quick_resolve_string +// Macro to facilitate adding new allocation entrypoints. +.macro ONE_ARG_DOWNCALL name, entrypoint, return + .extern \entrypoint +ENTRY \name SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC - # artResolveStringFromCode(Method* referrer, uint32_t string_idx, Thread*, $sp) - jal artResolveStringFromCode - move $a2, rSELF # pass Thread::Current - RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER -END art_quick_resolve_string + jal \entrypoint + move $a1, rSELF # pass Thread::Current + \return +END \name +.endm // Macro to facilitate adding new allocation entrypoints. .macro TWO_ARG_DOWNCALL name, entrypoint, return @@ -1312,6 +1269,31 @@ END \name GENERATE_ALL_ALLOC_ENTRYPOINTS /* + * Entry from managed code to resolve a string, this stub will allocate a String and deliver an + * exception on error. On success the String is returned. A0 holds the string index. The fast + * path check for hit in strings cache has already been performed. + */ +ONE_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER + + /* + * Entry from managed code when uninitialized static storage, this stub will run the class + * initializer and deliver the exception on error. On success the static storage base is + * returned. + */ +ONE_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER + + /* + * Entry from managed code when dex cache misses for a type_idx. + */ +ONE_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER + + /* + * Entry from managed code when type_idx needs to be checked for access and dex cache may also + * miss. + */ +ONE_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER + + /* * Called by managed code when the value in rSUSPEND has been decremented to 0. */ .extern artTestSuspendFromCode diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S index c5d8b8fc9b..55e3dff76c 100644 --- a/runtime/arch/x86/quick_entrypoints_x86.S +++ b/runtime/arch/x86/quick_entrypoints_x86.S @@ -910,10 +910,10 @@ GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_region_tlab_instrument GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_region_tlab_instrumented, RegionTLABInstrumented) GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_region_tlab_instrumented, RegionTLABInstrumented) -TWO_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO -TWO_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO -TWO_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO -TWO_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO +ONE_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO +ONE_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO +ONE_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO +ONE_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO TWO_ARG_REF_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S index 8185deb9e2..570624c054 100644 --- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S +++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S @@ -980,10 +980,10 @@ GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_region_tlab_instrument GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_region_tlab_instrumented, RegionTLABInstrumented) GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_region_tlab_instrumented, RegionTLABInstrumented) -TWO_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO -TWO_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO -TWO_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO -TWO_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO +ONE_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO +ONE_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO +ONE_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO +ONE_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO TWO_ARG_REF_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO diff --git a/runtime/barrier.cc b/runtime/barrier.cc index 66ee8709a7..f80a65f0ba 100644 --- a/runtime/barrier.cc +++ b/runtime/barrier.cc @@ -86,7 +86,7 @@ void Barrier::SetCountLocked(Thread* self, int count) { } Barrier::~Barrier() { - CHECK(!count_) << "Attempted to destroy barrier with non zero count"; + CHECK_EQ(count_, 0) << "Attempted to destroy barrier with non zero count"; } } // namespace art diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h index 64b7ecdabe..9292cff88e 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -22,6 +22,8 @@ #include "class_linker-inl.h" #include "common_throws.h" #include "dex_file.h" +#include "entrypoints/quick/callee_save_frame.h" +#include "handle_scope-inl.h" #include "indirect_reference_table.h" #include "invoke_type.h" #include "jni_internal.h" @@ -30,11 +32,31 @@ #include "mirror/class-inl.h" #include "mirror/object-inl.h" #include "mirror/throwable.h" -#include "handle_scope-inl.h" +#include "nth_caller_visitor.h" +#include "runtime.h" #include "thread.h" namespace art { +inline mirror::ArtMethod* GetCalleeSaveMethodCaller(Thread* self, Runtime::CalleeSaveType type) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + auto* refs_only_sp = self->GetManagedStack()->GetTopQuickFrame(); + DCHECK_EQ(refs_only_sp->AsMirrorPtr(), Runtime::Current()->GetCalleeSaveMethod(type)); + + const size_t callee_frame_size = GetCalleeSaveFrameSize(kRuntimeISA, type); + auto* caller_sp = reinterpret_cast<StackReference<mirror::ArtMethod>*>( + reinterpret_cast<uintptr_t>(refs_only_sp) + callee_frame_size); + auto* caller = caller_sp->AsMirrorPtr(); + + if (kIsDebugBuild) { + NthCallerVisitor visitor(self, 1, true); + visitor.WalkStack(); + CHECK(caller == visitor.caller); + } + + return caller; +} + template <const bool kAccessCheck> ALWAYS_INLINE inline mirror::Class* CheckObjectAlloc(uint32_t type_idx, diff --git a/runtime/entrypoints/quick/quick_default_externs.h b/runtime/entrypoints/quick/quick_default_externs.h index b7e8d50790..1fd8a949a9 100644 --- a/runtime/entrypoints/quick/quick_default_externs.h +++ b/runtime/entrypoints/quick/quick_default_externs.h @@ -34,10 +34,10 @@ class Object; extern "C" void art_quick_check_cast(const art::mirror::Class*, const art::mirror::Class*); // DexCache entrypoints. -extern "C" void* art_quick_initialize_static_storage(uint32_t, art::mirror::ArtMethod*); -extern "C" void* art_quick_initialize_type(uint32_t, art::mirror::ArtMethod*); -extern "C" void* art_quick_initialize_type_and_verify_access(uint32_t, art::mirror::ArtMethod*); -extern "C" void* art_quick_resolve_string(uint32_t, art::mirror::ArtMethod*); +extern "C" void* art_quick_initialize_static_storage(uint32_t); +extern "C" void* art_quick_initialize_type(uint32_t); +extern "C" void* art_quick_initialize_type_and_verify_access(uint32_t); +extern "C" void* art_quick_resolve_string(uint32_t); // Field entrypoints. extern "C" int art_quick_set8_instance(uint32_t, void*, int8_t); diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc index 348495d354..46629f5958 100644 --- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc @@ -26,41 +26,41 @@ namespace art { extern "C" mirror::Class* artInitializeStaticStorageFromCode(uint32_t type_idx, - mirror::ArtMethod* referrer, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Called to ensure static storage base is initialized for direct static field reads and writes. // A class may be accessing another class' fields when it doesn't have access, as access has been // given by inheritance. ScopedQuickEntrypointChecks sqec(self); - return ResolveVerifyAndClinit(type_idx, referrer, self, true, false); + auto* caller = GetCalleeSaveMethodCaller(self, Runtime::kRefsOnly); + return ResolveVerifyAndClinit(type_idx, caller, self, true, false); } extern "C" mirror::Class* artInitializeTypeFromCode(uint32_t type_idx, - mirror::ArtMethod* referrer, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Called when method->dex_cache_resolved_types_[] misses. ScopedQuickEntrypointChecks sqec(self); - return ResolveVerifyAndClinit(type_idx, referrer, self, false, false); + auto* caller = GetCalleeSaveMethodCaller(self, Runtime::kRefsOnly); + return ResolveVerifyAndClinit(type_idx, caller, self, false, false); } extern "C" mirror::Class* artInitializeTypeAndVerifyAccessFromCode(uint32_t type_idx, - mirror::ArtMethod* referrer, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Called when caller isn't guaranteed to have access to a type and the dex cache may be // unpopulated. ScopedQuickEntrypointChecks sqec(self); - return ResolveVerifyAndClinit(type_idx, referrer, self, false, true); + auto* caller = GetCalleeSaveMethodCaller(self, Runtime::kRefsOnly); + return ResolveVerifyAndClinit(type_idx, caller, self, false, true); } extern "C" mirror::String* artResolveStringFromCode(int32_t string_idx, - mirror::ArtMethod* referrer, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - return ResolveStringFromCode(referrer, string_idx); + auto* caller = GetCalleeSaveMethodCaller(self, Runtime::kRefsOnly); + return ResolveStringFromCode(caller, string_idx); } } // namespace art diff --git a/runtime/entrypoints/quick/quick_entrypoints_list.h b/runtime/entrypoints/quick/quick_entrypoints_list.h index eaf874eae8..6d9e483a9c 100644 --- a/runtime/entrypoints/quick/quick_entrypoints_list.h +++ b/runtime/entrypoints/quick/quick_entrypoints_list.h @@ -33,10 +33,10 @@ V(InstanceofNonTrivial, uint32_t, const mirror::Class*, const mirror::Class*) \ V(CheckCast, void, const mirror::Class*, const mirror::Class*) \ \ - V(InitializeStaticStorage, void*, uint32_t, mirror::ArtMethod*) \ - V(InitializeTypeAndVerifyAccess, void*, uint32_t, mirror::ArtMethod*) \ - V(InitializeType, void*, uint32_t, mirror::ArtMethod*) \ - V(ResolveString, void*, uint32_t, mirror::ArtMethod*) \ + V(InitializeStaticStorage, void*, uint32_t) \ + V(InitializeTypeAndVerifyAccess, void*, uint32_t) \ + V(InitializeType, void*, uint32_t) \ + V(ResolveString, void*, uint32_t) \ \ V(Set8Instance, int, uint32_t, void*, int8_t) \ V(Set8Static, int, uint32_t, int8_t) \ diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc index af01a02787..8524348164 100644 --- a/runtime/native/dalvik_system_ZygoteHooks.cc +++ b/runtime/native/dalvik_system_ZygoteHooks.cc @@ -65,6 +65,7 @@ static void EnableDebugFeatures(uint32_t debug_flags) { DEBUG_ENABLE_SAFEMODE = 1 << 3, DEBUG_ENABLE_JNI_LOGGING = 1 << 4, DEBUG_ENABLE_JIT = 1 << 5, + DEBUG_GENERATE_CFI = 1 << 6, }; Runtime* const runtime = Runtime::Current(); @@ -111,6 +112,12 @@ static void EnableDebugFeatures(uint32_t debug_flags) { } runtime->GetJITOptions()->SetUseJIT(use_jit); + const bool generate_cfi = (debug_flags & DEBUG_GENERATE_CFI) != 0; + if (generate_cfi) { + runtime->AddCompilerOption("--include-cfi"); + debug_flags &= ~DEBUG_GENERATE_CFI; + } + // This is for backwards compatibility with Dalvik. debug_flags &= ~DEBUG_ENABLE_ASSERT; diff --git a/runtime/reflection.cc b/runtime/reflection.cc index e54673831f..3099094ed4 100644 --- a/runtime/reflection.cc +++ b/runtime/reflection.cc @@ -615,11 +615,21 @@ jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaM // Wrap any exception with "Ljava/lang/reflect/InvocationTargetException;" and return early. if (soa.Self()->IsExceptionPending()) { + // If we get another exception when we are trying to wrap, then just use that instead. jthrowable th = soa.Env()->ExceptionOccurred(); - soa.Env()->ExceptionClear(); + soa.Self()->ClearException(); jclass exception_class = soa.Env()->FindClass("java/lang/reflect/InvocationTargetException"); + if (exception_class == nullptr) { + soa.Self()->AssertPendingOOMException(); + return nullptr; + } jmethodID mid = soa.Env()->GetMethodID(exception_class, "<init>", "(Ljava/lang/Throwable;)V"); + CHECK(mid != nullptr); jobject exception_instance = soa.Env()->NewObject(exception_class, mid, th); + if (exception_instance == nullptr) { + soa.Self()->AssertPendingOOMException(); + return nullptr; + } soa.Env()->Throw(reinterpret_cast<jthrowable>(exception_instance)); return nullptr; } diff --git a/runtime/stack.cc b/runtime/stack.cc index aa3e320127..e49bc1d78f 100644 --- a/runtime/stack.cc +++ b/runtime/stack.cc @@ -345,7 +345,7 @@ bool StackVisitor::SetVReg(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_val DCHECK(context_ != nullptr); // You can't reliably write registers without a context. DCHECK(m == GetMethod()); if (m->IsOptimized(sizeof(void*))) { - return SetVRegFromOptimizedCode(m, vreg, new_value, kind); + return false; } else { return SetVRegFromQuickCode(m, vreg, new_value, kind); } @@ -382,57 +382,6 @@ bool StackVisitor::SetVRegFromQuickCode(mirror::ArtMethod* m, uint16_t vreg, uin } } -bool StackVisitor::SetVRegFromOptimizedCode(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_value, - VRegKind kind) { - const void* code_pointer = m->GetQuickOatCodePointer(sizeof(void*)); - DCHECK(code_pointer != nullptr); - uint32_t native_pc_offset = m->NativeQuickPcOffset(cur_quick_frame_pc_); - CodeInfo code_info = m->GetOptimizedCodeInfo(); - StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset); - const DexFile::CodeItem* code_item = m->GetCodeItem(); - DCHECK(code_item != nullptr) << PrettyMethod(m); // Can't be null or how would we compile - // its instructions? - uint16_t number_of_dex_registers = code_item->registers_size_; - DCHECK_LT(vreg, number_of_dex_registers); - DexRegisterMap dex_register_map = - code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers); - DexRegisterLocation::Kind location_kind = - dex_register_map.GetLocationKind(vreg, number_of_dex_registers, code_info); - uint32_t dex_pc = m->ToDexPc(cur_quick_frame_pc_, false); - switch (location_kind) { - case DexRegisterLocation::Kind::kInStack: { - const int32_t offset = - dex_register_map.GetStackOffsetInBytes(vreg, number_of_dex_registers, code_info); - uint8_t* addr = reinterpret_cast<uint8_t*>(cur_quick_frame_) + offset; - *reinterpret_cast<uint32_t*>(addr) = new_value; - return true; - } - case DexRegisterLocation::Kind::kInRegister: - case DexRegisterLocation::Kind::kInFpuRegister: { - uint32_t reg = dex_register_map.GetMachineRegister(vreg, number_of_dex_registers, code_info); - return SetRegisterIfAccessible(reg, new_value, kind); - } - case DexRegisterLocation::Kind::kConstant: - LOG(ERROR) << StringPrintf("Cannot change value of DEX register v%u used as a constant at " - "DEX pc 0x%x (native pc 0x%x) of method %s", - vreg, dex_pc, native_pc_offset, - PrettyMethod(cur_quick_frame_->AsMirrorPtr()).c_str()); - return false; - case DexRegisterLocation::Kind::kNone: - LOG(ERROR) << StringPrintf("No location for DEX register v%u at DEX pc 0x%x " - "(native pc 0x%x) of method %s", - vreg, dex_pc, native_pc_offset, - PrettyMethod(cur_quick_frame_->AsMirrorPtr()).c_str()); - return false; - default: - LOG(FATAL) << StringPrintf("Unknown location for DEX register v%u at DEX pc 0x%x " - "(native pc 0x%x) of method %s", - vreg, dex_pc, native_pc_offset, - PrettyMethod(cur_quick_frame_->AsMirrorPtr()).c_str()); - UNREACHABLE(); - } -} - bool StackVisitor::SetRegisterIfAccessible(uint32_t reg, uint32_t new_value, VRegKind kind) { const bool is_float = (kind == kFloatVReg) || (kind == kDoubleLoVReg) || (kind == kDoubleHiVReg); if (!IsAccessibleRegister(reg, is_float)) { @@ -477,7 +426,7 @@ bool StackVisitor::SetVRegPair(mirror::ArtMethod* m, uint16_t vreg, uint64_t new DCHECK(context_ != nullptr); // You can't reliably write registers without a context. DCHECK(m == GetMethod()); if (m->IsOptimized(sizeof(void*))) { - return SetVRegPairFromOptimizedCode(m, vreg, new_value, kind_lo, kind_hi); + return false; } else { return SetVRegPairFromQuickCode(m, vreg, new_value, kind_lo, kind_hi); } @@ -515,15 +464,6 @@ bool StackVisitor::SetVRegPairFromQuickCode( } } -bool StackVisitor::SetVRegPairFromOptimizedCode( - mirror::ArtMethod* m, uint16_t vreg, uint64_t new_value, VRegKind kind_lo, VRegKind kind_hi) { - uint32_t low_32bits = Low32Bits(new_value); - uint32_t high_32bits = High32Bits(new_value); - bool success = SetVRegFromOptimizedCode(m, vreg, low_32bits, kind_lo); - success &= SetVRegFromOptimizedCode(m, vreg + 1, high_32bits, kind_hi); - return success; -} - bool StackVisitor::SetRegisterPairIfAccessible(uint32_t reg_lo, uint32_t reg_hi, uint64_t new_value, bool is_float) { if (!IsAccessibleRegister(reg_lo, is_float) || !IsAccessibleRegister(reg_hi, is_float)) { diff --git a/runtime/stack.h b/runtime/stack.h index ed9e458529..e2af5eefd2 100644 --- a/runtime/stack.h +++ b/runtime/stack.h @@ -668,18 +668,12 @@ class StackVisitor { bool SetVRegFromQuickCode(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_value, VRegKind kind) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool SetVRegFromOptimizedCode(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_value, - VRegKind kind) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool SetRegisterIfAccessible(uint32_t reg, uint32_t new_value, VRegKind kind) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool SetVRegPairFromQuickCode(mirror::ArtMethod* m, uint16_t vreg, uint64_t new_value, VRegKind kind_lo, VRegKind kind_hi) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool SetVRegPairFromOptimizedCode(mirror::ArtMethod* m, uint16_t vreg, uint64_t new_value, - VRegKind kind_lo, VRegKind kind_hi) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool SetRegisterPairIfAccessible(uint32_t reg_lo, uint32_t reg_hi, uint64_t new_value, bool is_float) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/runtime/thread.cc b/runtime/thread.cc index fa65bceff1..9f7c303af9 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -572,13 +572,13 @@ void Thread::ShortDump(std::ostream& os) const { if (GetThreadId() != 0) { // If we're in kStarting, we won't have a thin lock id or tid yet. os << GetThreadId() - << ",tid=" << GetTid() << ','; + << ",tid=" << GetTid() << ','; } os << GetState() - << ",Thread*=" << this - << ",peer=" << tlsPtr_.opeer - << ",\"" << *tlsPtr_.name << "\"" - << "]"; + << ",Thread*=" << this + << ",peer=" << tlsPtr_.opeer + << ",\"" << (tlsPtr_.name != nullptr ? *tlsPtr_.name : "null") << "\"" + << "]"; } void Thread::Dump(std::ostream& os) const { @@ -1171,9 +1171,14 @@ bool Thread::IsStillStarting() const { } void Thread::AssertPendingException() const { - if (UNLIKELY(!IsExceptionPending())) { - LOG(FATAL) << "Pending exception expected."; - } + CHECK(IsExceptionPending()) << "Pending exception expected."; +} + +void Thread::AssertPendingOOMException() const { + AssertPendingException(); + auto* e = GetException(); + CHECK_EQ(e->GetClass(), DecodeJObject(WellKnownClasses::java_lang_OutOfMemoryError)->AsClass()) + << e->Dump(); } void Thread::AssertNoPendingException() const { diff --git a/runtime/thread.h b/runtime/thread.h index dd9e7345df..35b785df63 100644 --- a/runtime/thread.h +++ b/runtime/thread.h @@ -336,6 +336,7 @@ class Thread { } void AssertPendingException() const; + void AssertPendingOOMException() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void AssertNoPendingException() const; void AssertNoPendingExceptionForNewException(const char* msg) const; diff --git a/runtime/utils_test.cc b/runtime/utils_test.cc index ae24b77625..d8f8950fbd 100644 --- a/runtime/utils_test.cc +++ b/runtime/utils_test.cc @@ -384,7 +384,8 @@ TEST_F(UtilsTest, GetSystemImageFilename) { TEST_F(UtilsTest, ExecSuccess) { std::vector<std::string> command; if (kIsTargetBuild) { - command.push_back("/system/bin/id"); + std::string android_root(GetAndroidRoot()); + command.push_back(android_root + "/bin/id"); } else { command.push_back("/usr/bin/id"); } diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc index a803df8b7e..a2d0427244 100644 --- a/runtime/well_known_classes.cc +++ b/runtime/well_known_classes.cc @@ -39,6 +39,7 @@ jclass WellKnownClasses::java_lang_ClassNotFoundException; jclass WellKnownClasses::java_lang_Daemons; jclass WellKnownClasses::java_lang_Error; jclass WellKnownClasses::java_lang_Object; +jclass WellKnownClasses::java_lang_OutOfMemoryError; jclass WellKnownClasses::java_lang_reflect_AbstractMethod; jclass WellKnownClasses::java_lang_reflect_ArtMethod; jclass WellKnownClasses::java_lang_reflect_Constructor; @@ -176,6 +177,7 @@ void WellKnownClasses::Init(JNIEnv* env) { java_lang_ClassNotFoundException = CacheClass(env, "java/lang/ClassNotFoundException"); java_lang_Daemons = CacheClass(env, "java/lang/Daemons"); java_lang_Object = CacheClass(env, "java/lang/Object"); + java_lang_OutOfMemoryError = CacheClass(env, "java/lang/OutOfMemoryError"); java_lang_Error = CacheClass(env, "java/lang/Error"); java_lang_reflect_AbstractMethod = CacheClass(env, "java/lang/reflect/AbstractMethod"); java_lang_reflect_ArtMethod = CacheClass(env, "java/lang/reflect/ArtMethod"); diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h index 2df1c0e6b0..cef9d55524 100644 --- a/runtime/well_known_classes.h +++ b/runtime/well_known_classes.h @@ -50,6 +50,7 @@ struct WellKnownClasses { static jclass java_lang_Daemons; static jclass java_lang_Error; static jclass java_lang_Object; + static jclass java_lang_OutOfMemoryError; static jclass java_lang_reflect_AbstractMethod; static jclass java_lang_reflect_ArtMethod; static jclass java_lang_reflect_Constructor; |