diff options
author | Ian Rogers <irogers@google.com> | 2013-02-27 08:32:07 -0800 |
---|---|---|
committer | Ian Rogers <irogers@google.com> | 2013-04-08 14:24:13 -0700 |
commit | 62d6c772205b8859f0ebf7ad105402ec4c3e2e01 (patch) | |
tree | e2f2ba6d71ed5a39c9f6909e3f7c08e998053315 /src/compiler | |
parent | c9b17c7ee96cd04fac9048aab624ed554fe260bf (diff) | |
download | android_art-62d6c772205b8859f0ebf7ad105402ec4c3e2e01.tar.gz android_art-62d6c772205b8859f0ebf7ad105402ec4c3e2e01.tar.bz2 android_art-62d6c772205b8859f0ebf7ad105402ec4c3e2e01.zip |
Interpreter entries and instrumentation as a listener.
Make the instrumentation responsible for whether we want method entry/exit
stubs, and allow it to use interpreter entry stubs when instruction by
instruction instrumentation is required. Improve deoptimization so more JDWP
test cases are passing.
Refactor exception debug posting, in particular improve reporting in the
interpreter. Improve class linker exception throwing so that broken dex files
are more likely to be reported. Fixes the performance issue Bug: 8410519.
Fix some error reporting lock level errors for the large object space. Make
fast object verification faster.
Add some debug mode robustness to finding dex PCs in GC maps.
Add printf attributes to JniAbortF and fix errors.
Expand run-test 044 to test return behaviors and fix issues with not throwing
appropriate exceptions for proxies.
Ensure causes are reported with a class linker NoClassDefFoundError and JNI
NoSuchFieldError.
Remove unused debugMe and updateDebuggerFromCode.
There's a minor sizing tweak to the arg array builder, and an extra reference
array check in the interpreter.
Some clean-up of trace code.
Fix reg type cache destructor if it is called after the reg type cache is
shutdown (as is the case in oatdump).
Change-Id: I6519c7b35df77f978d011999354c864f4918e8ce
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/dex/frontend.h | 1 | ||||
-rw-r--r-- | src/compiler/dex/quick/gen_common.cc | 11 | ||||
-rw-r--r-- | src/compiler/dex/quick/gen_invoke.cc | 3 | ||||
-rw-r--r-- | src/compiler/dex/quick/mir_to_lir.h | 1 | ||||
-rw-r--r-- | src/compiler/driver/compiler_driver.cc | 22 | ||||
-rw-r--r-- | src/compiler/llvm/runtime_support_llvm.cc | 92 |
6 files changed, 65 insertions, 65 deletions
diff --git a/src/compiler/dex/frontend.h b/src/compiler/dex/frontend.h index 2e62dc8c7b..49e085270c 100644 --- a/src/compiler/dex/frontend.h +++ b/src/compiler/dex/frontend.h @@ -55,7 +55,6 @@ enum opt_control_vector { // Force code generation paths for testing. enum debugControlVector { - kDebugDisplayMissingTargets, kDebugVerbose, kDebugDumpCFG, kDebugSlowFieldPath, diff --git a/src/compiler/dex/quick/gen_common.cc b/src/compiler/dex/quick/gen_common.cc index c13e79715a..4fadc9d361 100644 --- a/src/compiler/dex/quick/gen_common.cc +++ b/src/compiler/dex/quick/gen_common.cc @@ -507,17 +507,6 @@ void Mir2Lir::GenSget(uint32_t field_idx, RegLocation rl_dest, } } - -// Debugging routine - if null target, branch to DebugMe -void Mir2Lir::GenShowTarget() -{ - DCHECK_NE(cu_->instruction_set, kX86) << "unimplemented GenShowTarget"; - LIR* branch_over = OpCmpImmBranch(kCondNe, TargetReg(kInvokeTgt), 0, NULL); - LoadWordDisp(TargetReg(kSelf), ENTRYPOINT_OFFSET(pDebugMe), TargetReg(kInvokeTgt)); - LIR* target = NewLIR0(kPseudoTargetLabel); - branch_over->target = target; -} - void Mir2Lir::HandleSuspendLaunchPads() { LIR** suspend_label = reinterpret_cast<LIR**>(suspend_launchpads_.elem_list); diff --git a/src/compiler/dex/quick/gen_invoke.cc b/src/compiler/dex/quick/gen_invoke.cc index 3e946f89aa..c0bae29a95 100644 --- a/src/compiler/dex/quick/gen_invoke.cc +++ b/src/compiler/dex/quick/gen_invoke.cc @@ -1375,9 +1375,6 @@ void Mir2Lir::GenInvoke(CallInfo* info) vtable_idx, direct_code, direct_method, original_type); } - if (cu_->enable_debug & (1 << kDebugDisplayMissingTargets)) { - GenShowTarget(); - } LIR* call_inst; if (cu_->instruction_set != kX86) { call_inst = OpReg(kOpBlx, TargetReg(kInvokeTgt)); diff --git a/src/compiler/dex/quick/mir_to_lir.h b/src/compiler/dex/quick/mir_to_lir.h index 69ebc7e21c..aec0cc1dc3 100644 --- a/src/compiler/dex/quick/mir_to_lir.h +++ b/src/compiler/dex/quick/mir_to_lir.h @@ -396,7 +396,6 @@ class Mir2Lir : public Backend { bool is_long_or_double, bool is_object); void GenSget(uint32_t field_idx, RegLocation rl_dest, bool is_long_or_double, bool is_object); - void GenShowTarget(); void GenIGet(uint32_t field_idx, int opt_flags, OpSize size, RegLocation rl_dest, RegLocation rl_obj, bool is_long_or_double, bool is_object); void GenIPut(uint32_t field_idx, int opt_flags, OpSize size, diff --git a/src/compiler/driver/compiler_driver.cc b/src/compiler/driver/compiler_driver.cc index 700936c881..4e8ebbd4ef 100644 --- a/src/compiler/driver/compiler_driver.cc +++ b/src/compiler/driver/compiler_driver.cc @@ -1202,9 +1202,8 @@ static void VerifyClass(const ParallelCompilationManager* manager, size_t class_ manager->GetClassLinker()->FindClass(descriptor, soa.Decode<mirror::ClassLoader*>(manager->GetClassLoader())); if (klass == NULL) { - Thread* self = Thread::Current(); - CHECK(self->IsExceptionPending()); - self->ClearException(); + CHECK(soa.Self()->IsExceptionPending()); + soa.Self()->ClearException(); /* * At compile time, we can still structurally verify the class even if FindClass fails. @@ -1230,13 +1229,13 @@ static void VerifyClass(const ParallelCompilationManager* manager, size_t class_ if (klass->IsErroneous()) { // ClassLinker::VerifyClass throws, which isn't useful in the compiler. - CHECK(Thread::Current()->IsExceptionPending()); - Thread::Current()->ClearException(); + CHECK(soa.Self()->IsExceptionPending()); + soa.Self()->ClearException(); } CHECK(klass->IsCompileTimeVerified() || klass->IsErroneous()) << PrettyDescriptor(klass) << ": state=" << klass->GetStatus(); - CHECK(!Thread::Current()->IsExceptionPending()) << PrettyTypeOf(Thread::Current()->GetException()); + soa.Self()->AssertNoPendingException(); } void CompilerDriver::VerifyDexFile(jobject class_loader, const DexFile& dex_file, @@ -1435,7 +1434,6 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(manager->GetClassLoader()); const char* descriptor = manager->GetDexFile()->GetClassDescriptor(class_def); mirror::Class* klass = manager->GetClassLinker()->FindClass(descriptor, class_loader); - Thread* self = Thread::Current(); bool compiling_boot = Runtime::Current()->GetHeap()->GetSpaces().size() == 1; bool can_init_static_fields = compiling_boot && manager->GetCompiler()->IsImageClass(descriptor); @@ -1447,9 +1445,9 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl // its parents, whose locks are acquired. This leads to a parent-to-child and a child-to-parent // lock ordering and consequent potential deadlock. static Mutex lock1("Initializer lock", kMonitorLock); - MutexLock mu(self, lock1); + MutexLock mu(soa.Self(), lock1); // The lock required to initialize the class. - ObjectLock lock2(self, klass); + ObjectLock lock2(soa.Self(), klass); // Only try to initialize classes that were successfully verified. if (klass->IsVerified()) { manager->GetClassLinker()->EnsureInitialized(klass, false, can_init_static_fields); @@ -1473,7 +1471,7 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl } else { manager->GetClassLinker()->EnsureInitialized(klass, true, can_init_static_fields); } - CHECK(!self->IsExceptionPending()) << self->GetException()->Dump(); + soa.Self()->AssertNoPendingException(); } } } @@ -1494,7 +1492,7 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl } } // Clear any class not found or verification exceptions. - self->ClearException(); + soa.Self()->ClearException(); } void CompilerDriver::InitializeClasses(jobject jni_class_loader, const DexFile& dex_file, @@ -1651,7 +1649,7 @@ void CompilerDriver::CompileMethod(const DexFile::CodeItem* code_item, uint32_t if (self->IsExceptionPending()) { ScopedObjectAccess soa(self); LOG(FATAL) << "Unexpected exception compiling: " << PrettyMethod(method_idx, dex_file) << "\n" - << self->GetException()->Dump(); + << self->GetException(NULL)->Dump(); } } diff --git a/src/compiler/llvm/runtime_support_llvm.cc b/src/compiler/llvm/runtime_support_llvm.cc index d9b879afbd..d6c81813ad 100644 --- a/src/compiler/llvm/runtime_support_llvm.cc +++ b/src/compiler/llvm/runtime_support_llvm.cc @@ -135,15 +135,16 @@ void art_portable_unlock_object_from_code(mirror::Object* obj, Thread* thread) obj->MonitorExit(thread); } -void art_portable_test_suspend_from_code(Thread* thread) +void art_portable_test_suspend_from_code(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - CheckSuspend(thread); - if (thread->ReadFlag(kEnterInterpreter)) { + CheckSuspend(self); + if (Runtime::Current()->GetInstrumentation()->ShouldPortableCodeDeoptimize()) { // Save out the shadow frame to the heap - ShadowFrameCopyVisitor visitor(thread); + ShadowFrameCopyVisitor visitor(self); visitor.WalkStack(true); - thread->SetDeoptimizationShadowFrame(visitor.GetShadowFrameCopy(), JValue()); - thread->SetException(reinterpret_cast<mirror::Throwable*>(-1)); + self->SetDeoptimizationShadowFrame(visitor.GetShadowFrameCopy()); + self->SetDeoptimizationReturnValue(JValue()); + self->SetException(ThrowLocation(), reinterpret_cast<mirror::Throwable*>(-1)); } } @@ -175,51 +176,59 @@ bool art_portable_is_exception_pending_from_code() { } void art_portable_throw_div_zero_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Thread::Current()->ThrowNewException("Ljava/lang/ArithmeticException;", - "divide by zero"); + ThrowArithmeticExceptionDivideByZero(Thread::Current()); } void art_portable_throw_array_bounds_from_code(int32_t index, int32_t length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;", - "length=%d; index=%d", length, index); + ThrowArrayIndexOutOfBoundsException(index, length); } void art_portable_throw_no_such_method_from_code(int32_t method_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - // We need the calling method as context for the method_idx. - mirror::AbstractMethod* method = Thread::Current()->GetCurrentMethod(); - ThrowNoSuchMethodError(method_idx, method); + ThrowNoSuchMethodError(method_idx); } void art_portable_throw_null_pointer_exception_from_code(uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::AbstractMethod* throw_method = - Thread::Current()->GetManagedStack()->GetTopShadowFrame()->GetMethod(); - ThrowNullPointerExceptionFromDexPC(throw_method, dex_pc); + // TODO: remove dex_pc argument from caller. + UNUSED(dex_pc); + Thread* self = Thread::Current(); + ThrowLocation throw_location = self->GetCurrentLocationForThrow(); + ThrowNullPointerExceptionFromDexPC(throw_location); } void art_portable_throw_stack_overflow_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ThrowStackOverflowError(Thread::Current()); } -void art_portable_throw_exception_from_code(mirror::Object* exception) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Thread::Current()->DeliverException(static_cast<mirror::Throwable*>(exception)); +void art_portable_throw_exception_from_code(mirror::Throwable* exception) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + Thread* self = Thread::Current(); + ThrowLocation throw_location = self->GetCurrentLocationForThrow(); + if (exception == NULL) { + ThrowNullPointerException(NULL, "throw with null exception"); + } else { + self->SetException(throw_location, exception); + } } void* art_portable_get_and_clear_exception(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(self->IsExceptionPending()); - mirror::Throwable* exception = self->GetException(); + // TODO: make this inline. + mirror::Throwable* exception = self->GetException(NULL); self->ClearException(); return exception; } int32_t art_portable_find_catch_block_from_code(mirror::AbstractMethod* current_method, uint32_t ti_offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::Throwable* exception = Thread::Current()->GetException(); - // Check for magic deoptimization exception. - if (reinterpret_cast<int32_t>(exception) == -1) { + Thread* self = Thread::Current(); // TODO: make an argument. + ThrowLocation throw_location; + mirror::Throwable* exception = self->GetException(&throw_location); + // Check for special deoptimization exception. + if (UNLIKELY(reinterpret_cast<int32_t>(exception) == -1)) { return -1; } mirror::Class* exception_type = exception->GetClass(); @@ -229,26 +238,40 @@ int32_t art_portable_find_catch_block_from_code(mirror::AbstractMethod* current_ const DexFile::TryItem* try_item = DexFile::GetTryItems(*code_item, ti_offset); int iter_index = 0; + int result = -1; + uint32_t catch_dex_pc = -1; // Iterate over the catch handlers associated with dex_pc for (CatchHandlerIterator it(*code_item, *try_item); it.HasNext(); it.Next()) { uint16_t iter_type_idx = it.GetHandlerTypeIndex(); // Catch all case if (iter_type_idx == DexFile::kDexNoIndex16) { - return iter_index; + catch_dex_pc = it.GetHandlerAddress(); + result = iter_index; + break; } // Does this catch exception type apply? mirror::Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx); - if (iter_exception_type == NULL) { - // The verifier should take care of resolving all exception classes early + if (UNLIKELY(iter_exception_type == NULL)) { + // TODO: check, the verifier (class linker?) should take care of resolving all exception + // classes early. LOG(WARNING) << "Unresolved exception class when finding catch block: " << mh.GetTypeDescriptorFromTypeIdx(iter_type_idx); } else if (iter_exception_type->IsAssignableFrom(exception_type)) { - return iter_index; + catch_dex_pc = it.GetHandlerAddress(); + result = iter_index; + break; } ++iter_index; } - // Handler not found - return -1; + if (result != -1) { + // Handler found. + Runtime::Current()->GetInstrumentation()->ExceptionCaughtEvent(self, + throw_location, + current_method, + catch_dex_pc, + exception); + } + return result; } @@ -640,14 +663,12 @@ void art_portable_check_cast_from_code(const mirror::Class* dest_type, const mir DCHECK(dest_type->IsClass()) << PrettyClass(dest_type); DCHECK(src_type->IsClass()) << PrettyClass(src_type); if (UNLIKELY(!dest_type->IsAssignableFrom(src_type))) { - Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassCastException;", - "%s cannot be cast to %s", - PrettyDescriptor(src_type).c_str(), - PrettyDescriptor(dest_type).c_str()); + ThrowClassCastException(dest_type, src_type); } } -void art_portable_check_put_array_element_from_code(const mirror::Object* element, const mirror::Object* array) +void art_portable_check_put_array_element_from_code(const mirror::Object* element, + const mirror::Object* array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (element == NULL) { return; @@ -658,10 +679,7 @@ void art_portable_check_put_array_element_from_code(const mirror::Object* elemen mirror::Class* component_type = array_class->GetComponentType(); mirror::Class* element_class = element->GetClass(); if (UNLIKELY(!component_type->IsAssignableFrom(element_class))) { - Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;", - "%s cannot be stored in an array of type %s", - PrettyDescriptor(element_class).c_str(), - PrettyDescriptor(array_class).c_str()); + ThrowArrayStoreException(element_class, array_class); } return; } |