summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dex2oat/dex2oat_test.cc1
-rw-r--r--libartbase/base/mem_map_test.cc6
-rw-r--r--libdexfile/dex/dex_instruction_iterator.h1
-rw-r--r--openjdkjvmti/transform.cc1
-rw-r--r--runtime/instrumentation.h9
-rw-r--r--runtime/intern_table.cc1
-rw-r--r--runtime/interpreter/interpreter.cc8
-rw-r--r--runtime/interpreter/interpreter_common.h17
-rw-r--r--runtime/interpreter/interpreter_switch_impl-inl.h37
-rw-r--r--runtime/interpreter/mterp/mterp.cc8
-rw-r--r--runtime/mirror/class.cc1
-rw-r--r--runtime/native/dalvik_system_ZygoteHooks.cc4
-rw-r--r--runtime/native/java_lang_String.cc1
-rw-r--r--runtime/native/java_lang_StringFactory.cc1
-rw-r--r--runtime/native/libcore_util_CharsetUtils.cc1
-rw-r--r--runtime/runtime.cc5
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;