diff options
| -rw-r--r-- | dex2oat/dex2oat_test.cc | 1 | ||||
| -rw-r--r-- | libartbase/base/mem_map_test.cc | 6 | ||||
| -rw-r--r-- | libdexfile/dex/dex_instruction_iterator.h | 1 | ||||
| -rw-r--r-- | openjdkjvmti/transform.cc | 1 | ||||
| -rw-r--r-- | runtime/instrumentation.h | 9 | ||||
| -rw-r--r-- | runtime/intern_table.cc | 1 | ||||
| -rw-r--r-- | runtime/interpreter/interpreter.cc | 8 | ||||
| -rw-r--r-- | runtime/interpreter/interpreter_common.h | 17 | ||||
| -rw-r--r-- | runtime/interpreter/interpreter_switch_impl-inl.h | 37 | ||||
| -rw-r--r-- | runtime/interpreter/mterp/mterp.cc | 8 | ||||
| -rw-r--r-- | runtime/mirror/class.cc | 1 | ||||
| -rw-r--r-- | runtime/native/dalvik_system_ZygoteHooks.cc | 4 | ||||
| -rw-r--r-- | runtime/native/java_lang_String.cc | 1 | ||||
| -rw-r--r-- | runtime/native/java_lang_StringFactory.cc | 1 | ||||
| -rw-r--r-- | runtime/native/libcore_util_CharsetUtils.cc | 1 | ||||
| -rw-r--r-- | runtime/runtime.cc | 5 |
16 files changed, 61 insertions, 41 deletions
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc index 898940a948..770b696d6b 100644 --- a/dex2oat/dex2oat_test.cc +++ b/dex2oat/dex2oat_test.cc @@ -39,6 +39,7 @@ #include "dex/dex_file_loader.h" #include "dex2oat_environment_test.h" #include "dex2oat_return_codes.h" +#include "gc_root-inl.h" #include "intern_table-inl.h" #include "oat.h" #include "oat_file.h" diff --git a/libartbase/base/mem_map_test.cc b/libartbase/base/mem_map_test.cc index 813d90d0bd..e4e227f3b2 100644 --- a/libartbase/base/mem_map_test.cc +++ b/libartbase/base/mem_map_test.cc @@ -411,6 +411,12 @@ TEST_F(MemMapTest, MapFile32Bit) { #endif TEST_F(MemMapTest, MapAnonymousExactAddr) { + // TODO: The semantics of the MemMap::MapAnonymous() with a given address but without + // `reuse == true` or `reservation != nullptr` is weird. We should either drop support + // for it, or take it only as a hint and allow the result to be mapped elsewhere. + // Currently we're seeing failures with ASAN. b/118408378 + TEST_DISABLED_FOR_MEMORY_TOOL(); + CommonInit(); std::string error_msg; // Find a valid address. diff --git a/libdexfile/dex/dex_instruction_iterator.h b/libdexfile/dex/dex_instruction_iterator.h index b75a95bf5c..6c7f42a925 100644 --- a/libdexfile/dex/dex_instruction_iterator.h +++ b/libdexfile/dex/dex_instruction_iterator.h @@ -63,7 +63,6 @@ class DexInstructionIteratorBase : public using value_type = std::iterator<std::forward_iterator_tag, DexInstructionPcPair>::value_type; using difference_type = std::iterator<std::forward_iterator_tag, value_type>::difference_type; - DexInstructionIteratorBase() = default; explicit DexInstructionIteratorBase(const Instruction* inst, uint32_t dex_pc) : data_(reinterpret_cast<const uint16_t*>(inst), dex_pc) {} diff --git a/openjdkjvmti/transform.cc b/openjdkjvmti/transform.cc index 653f944d7c..8bd10dafcb 100644 --- a/openjdkjvmti/transform.cc +++ b/openjdkjvmti/transform.cc @@ -48,6 +48,7 @@ #include "events-inl.h" #include "fault_handler.h" #include "gc_root-inl.h" +#include "handle_scope-inl.h" #include "jni/jni_env_ext-inl.h" #include "jvalue.h" #include "jvmti.h" diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h index b3fae25210..3bd4fb54af 100644 --- a/runtime/instrumentation.h +++ b/runtime/instrumentation.h @@ -384,15 +384,6 @@ class Instrumentation { have_exception_handled_listeners_; } - // Any instrumentation *other* than what is needed for Jit profiling active? - bool NonJitProfilingActive() const REQUIRES_SHARED(Locks::mutator_lock_) { - return have_dex_pc_listeners_ || have_method_exit_listeners_ || - have_field_read_listeners_ || have_field_write_listeners_ || - have_exception_thrown_listeners_ || have_method_unwind_listeners_ || - have_branch_listeners_ || have_watched_frame_pop_listeners_ || - have_exception_handled_listeners_; - } - // Inform listeners that a method has been entered. A dex PC is provided as we may install // listeners into executing code and get method enter events for methods already on the stack. void MethodEnterEvent(Thread* thread, mirror::Object* this_object, diff --git a/runtime/intern_table.cc b/runtime/intern_table.cc index 6fbfbdd539..2449121548 100644 --- a/runtime/intern_table.cc +++ b/runtime/intern_table.cc @@ -23,6 +23,7 @@ #include "gc/space/image_space.h" #include "gc/weak_root_state.h" #include "gc_root-inl.h" +#include "handle_scope-inl.h" #include "image-inl.h" #include "mirror/dex_cache-inl.h" #include "mirror/object-inl.h" diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc index b37a2781b5..5784b9b898 100644 --- a/runtime/interpreter/interpreter.cc +++ b/runtime/interpreter/interpreter.cc @@ -248,6 +248,14 @@ static inline JValue Execute( bool from_deoptimize = false) REQUIRES_SHARED(Locks::mutator_lock_) { DCHECK(!shadow_frame.GetMethod()->IsAbstract()); DCHECK(!shadow_frame.GetMethod()->IsNative()); + + // Check that we are using the right interpreter. + if (kIsDebugBuild && self->UseMterp() != CanUseMterp()) { + // The flag might be currently being updated on all threads. Retry with lock. + MutexLock tll_mu(self, *Locks::thread_list_lock_); + DCHECK_EQ(self->UseMterp(), CanUseMterp()); + } + if (LIKELY(!from_deoptimize)) { // Entering the method, but not via deoptimization. if (kIsDebugBuild) { CHECK_EQ(shadow_frame.GetDexPC(), 0u); diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h index 96588c8738..9924aa5292 100644 --- a/runtime/interpreter/interpreter_common.h +++ b/runtime/interpreter/interpreter_common.h @@ -128,10 +128,8 @@ template<InvokeType type> static ALWAYS_INLINE bool UseInterpreterToInterpreterFastPath(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) { Runtime* runtime = Runtime::Current(); - if (!runtime->IsStarted()) { - return false; - } const void* quick_code = method->GetEntryPointFromQuickCompiledCode(); + DCHECK(runtime->IsStarted()); if (!runtime->GetClassLinker()->IsQuickToInterpreterBridge(quick_code)) { return false; } @@ -144,16 +142,11 @@ static ALWAYS_INLINE bool UseInterpreterToInterpreterFastPath(ArtMethod* method) if (type == kStatic && !method->GetDeclaringClass()->IsInitialized()) { return false; } - if (runtime->IsActiveTransaction() || runtime->GetInstrumentation()->HasMethodEntryListeners()) { - return false; - } + DCHECK(!runtime->IsActiveTransaction()); ProfilingInfo* profiling_info = method->GetProfilingInfo(kRuntimePointerSize); if ((profiling_info != nullptr) && (profiling_info->GetSavedEntryPoint() != nullptr)) { return false; } - if (runtime->GetJit() != nullptr && runtime->GetJit()->JitAtFirstUse()) { - return false; - } return true; } @@ -171,7 +164,9 @@ static ALWAYS_INLINE bool DoInvoke(Thread* self, JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { // Make sure to check for async exceptions before anything else. - if (UNLIKELY(self->ObserveAsyncException())) { + if (is_mterp && self->UseMterp()) { + DCHECK(!self->ObserveAsyncException()); + } else if (UNLIKELY(self->ObserveAsyncException())) { return false; } const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c(); @@ -229,7 +224,7 @@ static ALWAYS_INLINE bool DoInvoke(Thread* self, } } - if (is_mterp && UseInterpreterToInterpreterFastPath<type>(called_method)) { + if (is_mterp && self->UseMterp() && UseInterpreterToInterpreterFastPath<type>(called_method)) { const uint16_t number_of_inputs = (is_range) ? inst->VRegA_3rc(inst_data) : inst->VRegA_35c(inst_data); CodeItemDataAccessor accessor(called_method->DexInstructionData()); diff --git a/runtime/interpreter/interpreter_switch_impl-inl.h b/runtime/interpreter/interpreter_switch_impl-inl.h index 4774d6994e..c430de2b85 100644 --- a/runtime/interpreter/interpreter_switch_impl-inl.h +++ b/runtime/interpreter/interpreter_switch_impl-inl.h @@ -36,7 +36,7 @@ namespace art { namespace interpreter { #define CHECK_FORCE_RETURN() \ - do { \ + { \ if (UNLIKELY(shadow_frame.GetForcePopFrame())) { \ DCHECK(PrevFrameWillRetry(self, shadow_frame)) \ << "Pop frame forced without previous frame ready to retry instruction!"; \ @@ -53,10 +53,11 @@ namespace interpreter { ctx->result = JValue(); /* Handled in caller. */ \ return; \ } \ - } while (false) + } \ + do {} while (false) #define HANDLE_PENDING_EXCEPTION_WITH_INSTRUMENTATION(instr) \ - do { \ + { \ DCHECK(self->IsExceptionPending()); \ self->AllowThreadSuspension(); \ CHECK_FORCE_RETURN(); \ @@ -74,13 +75,15 @@ namespace interpreter { int32_t displacement = \ static_cast<int32_t>(shadow_frame.GetDexPC()) - static_cast<int32_t>(dex_pc); \ inst = inst->RelativeAt(displacement); \ + break; /* Stop executing this opcode and continue in the exception handler. */ \ } \ - } while (false) + } \ + do {} while (false) #define HANDLE_PENDING_EXCEPTION() HANDLE_PENDING_EXCEPTION_WITH_INSTRUMENTATION(instrumentation) #define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_IMPL(_is_exception_pending, _next_function) \ - do { \ + { \ if (UNLIKELY(shadow_frame.GetForceRetryInstruction())) { \ /* Don't need to do anything except clear the flag and exception. We leave the */ \ /* instruction the same so it will be re-executed on the next go-around. */ \ @@ -101,7 +104,8 @@ namespace interpreter { } else { \ inst = inst->_next_function(); \ } \ - } while (false) + } \ + do {} while (false) #define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(_is_exception_pending) \ POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_IMPL(_is_exception_pending, Next_4xx) @@ -109,7 +113,7 @@ namespace interpreter { POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_IMPL(_is_exception_pending, Next_3xx) #define POSSIBLY_HANDLE_PENDING_EXCEPTION(_is_exception_pending, _next_function) \ - do { \ + { \ /* Should only be on invoke instructions. */ \ DCHECK(!shadow_frame.GetForceRetryInstruction()); \ if (UNLIKELY(_is_exception_pending)) { \ @@ -117,7 +121,8 @@ namespace interpreter { } else { \ inst = inst->_next_function(); \ } \ - } while (false) + } \ + do {} while (false) #define HANDLE_MONITOR_CHECKS() \ if (!DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame)) { \ @@ -148,7 +153,7 @@ namespace interpreter { #define PREAMBLE() PREAMBLE_SAVE(nullptr) #define BRANCH_INSTRUMENTATION(offset) \ - do { \ + { \ if (UNLIKELY(instrumentation->HasBranchListeners())) { \ instrumentation->Branch(self, shadow_frame.GetMethod(), dex_pc, offset); \ } \ @@ -165,31 +170,33 @@ namespace interpreter { ctx->result = result; \ return; \ } \ - } while (false) + } \ + do {} while (false) #define HOTNESS_UPDATE() \ - do { \ + { \ if (jit != nullptr) { \ jit->AddSamples(self, shadow_frame.GetMethod(), 1, /*with_backedges=*/ true); \ } \ - } while (false) + } \ + do {} while (false) #define HANDLE_ASYNC_EXCEPTION() \ if (UNLIKELY(self->ObserveAsyncException())) { \ HANDLE_PENDING_EXCEPTION(); \ - break; \ } \ do {} while (false) #define HANDLE_BACKWARD_BRANCH(offset) \ - do { \ + { \ if (IsBackwardBranch(offset)) { \ HOTNESS_UPDATE(); \ /* Record new dex pc early to have consistent suspend point at loop header. */ \ shadow_frame.SetDexPC(inst->GetDexPc(insns)); \ self->AllowThreadSuspension(); \ } \ - } while (false) + } \ + do {} while (false) // Unlike most other events the DexPcMovedEvent can be sent when there is a pending exception (if // the next instruction is MOVE_EXCEPTION). This means it needs to be handled carefully to be able diff --git a/runtime/interpreter/mterp/mterp.cc b/runtime/interpreter/mterp/mterp.cc index 4b6f430e65..ba109bc2b7 100644 --- a/runtime/interpreter/mterp/mterp.cc +++ b/runtime/interpreter/mterp/mterp.cc @@ -146,15 +146,18 @@ bool CanUseMterp() REQUIRES_SHARED(Locks::mutator_lock_) { const Runtime* const runtime = Runtime::Current(); return + runtime->IsStarted() && + !runtime->IsAotCompiler() && !Dbg::IsDebuggerActive() && - !runtime->GetInstrumentation()->NonJitProfilingActive() && + !runtime->GetInstrumentation()->IsActive() && // mterp only knows how to deal with the normal exits. It cannot handle any of the // non-standard force-returns. !runtime->AreNonStandardExitsEnabled() && // An async exception has been thrown. We need to go to the switch interpreter. MTerp doesn't // know how to deal with these so we could end up never dealing with it if we are in an // infinite loop. - !runtime->AreAsyncExceptionsThrown(); + !runtime->AreAsyncExceptionsThrown() && + (runtime->GetJit() == nullptr || !runtime->GetJit()->JitAtFirstUse()); } @@ -560,6 +563,7 @@ extern "C" void MterpCheckBefore(Thread* self, ShadowFrame* shadow_frame, uint16 MutexLock tll_mu(self, *Locks::thread_list_lock_); DCHECK_EQ(self->UseMterp(), CanUseMterp()); } + DCHECK(!Runtime::Current()->IsActiveTransaction()); const Instruction* inst = Instruction::At(dex_pc_ptr); uint16_t inst_data = inst->Fetch16(0); if (inst->Opcode(inst_data) == Instruction::MOVE_EXCEPTION) { diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 6a378f0ca5..e65505298f 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -32,6 +32,7 @@ #include "dex/dex_file_annotations.h" #include "dex_cache.h" #include "gc/accounting/card_table-inl.h" +#include "gc/heap-inl.h" #include "handle_scope-inl.h" #include "subtype_check.h" #include "method.h" diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc index f54bf87216..f5c0704098 100644 --- a/runtime/native/dalvik_system_ZygoteHooks.cc +++ b/runtime/native/dalvik_system_ZygoteHooks.cc @@ -225,7 +225,9 @@ static uint32_t EnableDebugFeatures(uint32_t runtime_flags) { if ((runtime_flags & DEBUG_ALWAYS_JIT) != 0) { jit::JitOptions* jit_options = runtime->GetJITOptions(); CHECK(jit_options != nullptr); - jit_options->SetJitAtFirstUse(); + Runtime::Current()->DoAndMaybeSwitchInterpreter([=]() { + jit_options->SetJitAtFirstUse(); + }); runtime_flags &= ~DEBUG_ALWAYS_JIT; } diff --git a/runtime/native/java_lang_String.cc b/runtime/native/java_lang_String.cc index 8976058b53..78ec859ef9 100644 --- a/runtime/native/java_lang_String.cc +++ b/runtime/native/java_lang_String.cc @@ -19,6 +19,7 @@ #include "nativehelper/jni_macros.h" #include "common_throws.h" +#include "handle_scope-inl.h" #include "jni/jni_internal.h" #include "mirror/array.h" #include "mirror/object-inl.h" diff --git a/runtime/native/java_lang_StringFactory.cc b/runtime/native/java_lang_StringFactory.cc index 3978ca8a36..c6ad4e40d1 100644 --- a/runtime/native/java_lang_StringFactory.cc +++ b/runtime/native/java_lang_StringFactory.cc @@ -17,6 +17,7 @@ #include "java_lang_StringFactory.h" #include "common_throws.h" +#include "handle_scope-inl.h" #include "jni/jni_internal.h" #include "mirror/object-inl.h" #include "mirror/string-inl.h" diff --git a/runtime/native/libcore_util_CharsetUtils.cc b/runtime/native/libcore_util_CharsetUtils.cc index 24298049ee..95e0d79cd9 100644 --- a/runtime/native/libcore_util_CharsetUtils.cc +++ b/runtime/native/libcore_util_CharsetUtils.cc @@ -18,6 +18,7 @@ #include <string.h> +#include "handle_scope-inl.h" #include "jni/jni_internal.h" #include "mirror/string-inl.h" #include "mirror/string.h" diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 40c7301456..a152692897 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -744,7 +744,7 @@ bool Runtime::Start() { self->TransitionFromRunnableToSuspended(kNative); - started_ = true; + DoAndMaybeSwitchInterpreter([=](){ started_ = true; }); if (!IsImageDex2OatEnabled() || !GetHeap()->HasBootImageSpace()) { ScopedObjectAccess soa(self); @@ -2488,7 +2488,8 @@ void Runtime::CreateJit() { DCHECK(!jit_options_->UseJitCompilation()); } std::string error_msg; - jit_.reset(jit::Jit::Create(jit_options_.get(), &error_msg)); + jit::Jit* jit = jit::Jit::Create(jit_options_.get(), &error_msg); + DoAndMaybeSwitchInterpreter([=](){ jit_.reset(jit); }); if (jit_.get() == nullptr) { LOG(WARNING) << "Failed to create JIT " << error_msg; return; |