Merge "Emit bit manipulation instructions for x86 and x86_64"
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index fc8cd52..599f4aa 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -188,13 +188,13 @@
compiler_options_->compile_pic_ = false; // Non-PIC boot image is a test configuration.
compiler_options_->SetCompilerFilter(GetCompilerFilter());
compiler_options_->image_classes_.swap(*GetImageClasses());
+ compiler_options_->profile_compilation_info_ = GetProfileCompilationInfo();
compiler_driver_.reset(new CompilerDriver(compiler_options_.get(),
verification_results_.get(),
compiler_kind_,
&compiler_options_->image_classes_,
number_of_threads_,
- /* swap_fd */ -1,
- GetProfileCompilationInfo()));
+ /* swap_fd */ -1));
}
void CommonCompilerTest::SetUpRuntimeOptions(RuntimeOptions* options) {
diff --git a/compiler/driver/compiled_method_storage_test.cc b/compiler/driver/compiled_method_storage_test.cc
index 5e2f444..8b35bd3 100644
--- a/compiler/driver/compiled_method_storage_test.cc
+++ b/compiler/driver/compiled_method_storage_test.cc
@@ -33,8 +33,7 @@
Compiler::kOptimizing,
/* image_classes */ nullptr,
/* thread_count */ 1u,
- /* swap_fd */ -1,
- /* profile_compilation_info */ nullptr);
+ /* swap_fd */ -1);
CompiledMethodStorage* storage = driver.GetCompiledMethodStorage();
ASSERT_TRUE(storage->DedupeEnabled()); // The default.
diff --git a/compiler/driver/compiler_driver-inl.h b/compiler/driver/compiler_driver-inl.h
index 294072d..792f508 100644
--- a/compiler/driver/compiler_driver-inl.h
+++ b/compiler/driver/compiler_driver-inl.h
@@ -99,25 +99,6 @@
return std::make_pair(fast_get, fast_put);
}
-inline ArtMethod* CompilerDriver::ResolveMethod(
- ScopedObjectAccess& soa,
- Handle<mirror::DexCache> dex_cache,
- Handle<mirror::ClassLoader> class_loader,
- const DexCompilationUnit* mUnit,
- uint32_t method_idx,
- InvokeType invoke_type) {
- DCHECK_EQ(class_loader.Get(), mUnit->GetClassLoader().Get());
- ArtMethod* resolved_method =
- mUnit->GetClassLinker()->ResolveMethod<ClassLinker::ResolveMode::kCheckICCEAndIAE>(
- method_idx, dex_cache, class_loader, /* referrer */ nullptr, invoke_type);
- if (UNLIKELY(resolved_method == nullptr)) {
- DCHECK(soa.Self()->IsExceptionPending());
- // Clean up any exception left by type resolution.
- soa.Self()->ClearException();
- }
- return resolved_method;
-}
-
inline VerificationResults* CompilerDriver::GetVerificationResults() const {
DCHECK(Runtime::Current()->IsAotCompiler());
return verification_results_;
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 8c276bb..f7bff4d 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -248,8 +248,7 @@
Compiler::Kind compiler_kind,
HashSet<std::string>* image_classes,
size_t thread_count,
- int swap_fd,
- const ProfileCompilationInfo* profile_compilation_info)
+ int swap_fd)
: compiler_options_(compiler_options),
verification_results_(verification_results),
compiler_(Compiler::Create(this, compiler_kind)),
@@ -259,9 +258,7 @@
had_hard_verifier_failure_(false),
parallel_thread_count_(thread_count),
stats_(new AOTCompilationStats),
- compiler_context_(nullptr),
compiled_method_storage_(swap_fd),
- profile_compilation_info_(profile_compilation_info),
max_arena_alloc_(0),
dex_to_dex_compiler_(this) {
DCHECK(compiler_options_ != nullptr);
@@ -731,9 +728,11 @@
continue;
}
+ const ProfileCompilationInfo* profile_compilation_info =
+ GetCompilerOptions().GetProfileCompilationInfo();
const bool is_startup_class =
- profile_compilation_info_ != nullptr &&
- profile_compilation_info_->ContainsClass(*dex_file, accessor.GetClassIdx());
+ profile_compilation_info != nullptr &&
+ profile_compilation_info->ContainsClass(*dex_file, accessor.GetClassIdx());
for (const ClassAccessor::Method& method : accessor.GetMethods()) {
const bool is_clinit = (method.GetAccessFlags() & kAccConstructor) != 0 &&
@@ -741,8 +740,8 @@
const bool is_startup_clinit = is_startup_class && is_clinit;
if (only_startup_strings &&
- profile_compilation_info_ != nullptr &&
- (!profile_compilation_info_->GetMethodHotness(method.GetReference()).IsStartup() &&
+ profile_compilation_info != nullptr &&
+ (!profile_compilation_info->GetMethodHotness(method.GetReference()).IsStartup() &&
!is_startup_clinit)) {
continue;
}
@@ -981,12 +980,14 @@
return true;
}
// If we are using a profile filter but do not have a profile compilation info, compile nothing.
- if (profile_compilation_info_ == nullptr) {
+ const ProfileCompilationInfo* profile_compilation_info =
+ GetCompilerOptions().GetProfileCompilationInfo();
+ if (profile_compilation_info == nullptr) {
return false;
}
// Compile only hot methods, it is the profile saver's job to decide what startup methods to mark
// as hot.
- bool result = profile_compilation_info_->GetMethodHotness(method_ref).IsHot();
+ bool result = profile_compilation_info->GetMethodHotness(method_ref).IsHot();
if (kDebugProfileGuidedCompilation) {
LOG(INFO) << "[ProfileGuidedCompilation] "
@@ -2644,10 +2645,12 @@
const std::vector<const DexFile*>& dex_files,
TimingLogger* timings) {
if (kDebugProfileGuidedCompilation) {
+ const ProfileCompilationInfo* profile_compilation_info =
+ GetCompilerOptions().GetProfileCompilationInfo();
LOG(INFO) << "[ProfileGuidedCompilation] " <<
- ((profile_compilation_info_ == nullptr)
+ ((profile_compilation_info == nullptr)
? "null"
- : profile_compilation_info_->DumpInfo(dex_files));
+ : profile_compilation_info->DumpInfo(dex_files));
}
dex_to_dex_compiler_.ClearState();
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index f42e555..94efdd8 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -99,8 +99,7 @@
Compiler::Kind compiler_kind,
HashSet<std::string>* image_classes,
size_t thread_count,
- int swap_fd,
- const ProfileCompilationInfo* profile_compilation_info);
+ int swap_fd);
~CompilerDriver();
@@ -146,7 +145,6 @@
bool GetCompiledClass(const ClassReference& ref, ClassStatus* status) const;
CompiledMethod* GetCompiledMethod(MethodReference ref) const;
- size_t GetNonRelativeLinkerPatchCount() const;
// Add a compiled method.
void AddCompiledMethod(const MethodReference& method_ref, CompiledMethod* const compiled_method);
CompiledMethod* RemoveCompiledMethod(const MethodReference& method_ref);
@@ -181,16 +179,6 @@
uint16_t field_idx)
REQUIRES_SHARED(Locks::mutator_lock_);
- // Resolve a method. Returns null on failure, including incompatible class change.
- ArtMethod* ResolveMethod(
- ScopedObjectAccess& soa,
- Handle<mirror::DexCache> dex_cache,
- Handle<mirror::ClassLoader> class_loader,
- const DexCompilationUnit* mUnit,
- uint32_t method_idx,
- InvokeType invoke_type)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
void ProcessedInstanceField(bool resolved);
void ProcessedStaticField(bool resolved, bool local);
@@ -209,14 +197,6 @@
const VerifiedMethod* GetVerifiedMethod(const DexFile* dex_file, uint32_t method_idx) const;
bool IsSafeCast(const DexCompilationUnit* mUnit, uint32_t dex_pc);
- void SetCompilerContext(void* compiler_context) {
- compiler_context_ = compiler_context;
- }
-
- void* GetCompilerContext() const {
- return compiler_context_;
- }
-
size_t GetThreadCount() const {
return parallel_thread_count_;
}
@@ -266,10 +246,6 @@
return &compiled_method_storage_;
}
- const ProfileCompilationInfo* GetProfileCompilationInfo() const {
- return profile_compilation_info_;
- }
-
// Is `boot_image_filename` the name of a core image (small boot
// image used for ART testing only)?
static bool IsCoreImageFilename(const std::string& boot_image_filename) {
@@ -363,6 +339,12 @@
void FreeThreadPools();
void CheckThreadPools();
+ // Resolve const string literals that are loaded from dex code. If only_startup_strings is
+ // specified, only methods that are marked startup in the profile are resolved.
+ void ResolveConstStrings(const std::vector<const DexFile*>& dex_files,
+ bool only_startup_strings,
+ /*inout*/ TimingLogger* timings);
+
const CompilerOptions* const compiler_options_;
VerificationResults* const verification_results_;
@@ -377,13 +359,6 @@
typedef AtomicDexRefMap<MethodReference, CompiledMethod*> MethodTable;
- private:
- // Resolve const string literals that are loaded from dex code. If only_startup_strings is
- // specified, only methods that are marked startup in the profile are resolved.
- void ResolveConstStrings(const std::vector<const DexFile*>& dex_files,
- bool only_startup_strings,
- /*inout*/ TimingLogger* timings);
-
// All method references that this compiler has compiled.
MethodTable compiled_methods_;
@@ -412,16 +387,8 @@
class AOTCompilationStats;
std::unique_ptr<AOTCompilationStats> stats_;
- typedef void (*CompilerCallbackFn)(CompilerDriver& driver);
- typedef MutexLock* (*CompilerMutexLockFn)(CompilerDriver& driver);
-
- void* compiler_context_;
-
CompiledMethodStorage compiled_method_storage_;
- // Info for profile guided compilation.
- const ProfileCompilationInfo* const profile_compilation_info_;
-
size_t max_arena_alloc_;
// Compiler for dex to dex (quickening).
diff --git a/compiler/driver/compiler_options.cc b/compiler/driver/compiler_options.cc
index 6b0e456..be8e10e 100644
--- a/compiler/driver/compiler_options.cc
+++ b/compiler/driver/compiler_options.cc
@@ -60,6 +60,7 @@
dump_pass_timings_(false),
dump_stats_(false),
top_k_profile_threshold_(kDefaultTopKProfileThreshold),
+ profile_compilation_info_(nullptr),
verbose_methods_(),
abort_on_hard_verifier_failure_(false),
abort_on_soft_verifier_failure_(false),
diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h
index 4a6bbfa..77f8482 100644
--- a/compiler/driver/compiler_options.h
+++ b/compiler/driver/compiler_options.h
@@ -42,6 +42,7 @@
class DexFile;
enum class InstructionSet;
class InstructionSetFeatures;
+class ProfileCompilationInfo;
class CompilerOptions final {
public:
@@ -218,6 +219,10 @@
return compile_pic_;
}
+ const ProfileCompilationInfo* GetProfileCompilationInfo() const {
+ return profile_compilation_info_;
+ }
+
bool HasVerboseMethods() const {
return !verbose_methods_.empty();
}
@@ -370,6 +375,9 @@
// When using a profile file only the top K% of the profiled samples will be compiled.
double top_k_profile_threshold_;
+ // Info for profile guided compilation.
+ const ProfileCompilationInfo* profile_compilation_info_;
+
// Vector of methods to have verbose output enabled for.
std::vector<std::string> verbose_methods_;
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index bc8641a..f22f61f 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -151,8 +151,7 @@
Compiler::kOptimizing,
/* image_classes */ nullptr,
/* thread_count */ 1,
- /* swap_fd */ -1,
- /* profile_compilation_info */ nullptr));
+ /* swap_fd */ -1));
// Disable dedupe so we can remove compiled methods.
compiler_driver_->SetDedupeEnabled(false);
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index f56f9cb..c1daf95 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -680,7 +680,7 @@
/*out*/Handle<mirror::ObjectArray<mirror::Class>>* inline_cache)
REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(Runtime::Current()->IsAotCompiler());
- const ProfileCompilationInfo* pci = compiler_driver_->GetProfileCompilationInfo();
+ const ProfileCompilationInfo* pci = codegen_->GetCompilerOptions().GetProfileCompilationInfo();
if (pci == nullptr) {
return kInlineCacheNoData;
}
@@ -1647,7 +1647,7 @@
}
}
if (needs_constructor_barrier) {
- // See CompilerDriver::RequiresConstructorBarrier for more details.
+ // See DexCompilationUnit::RequiresConstructorBarrier for more details.
DCHECK(obj != nullptr) << "only non-static methods can have a constructor fence";
HConstructorFence* constructor_fence =
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index f0f2b3e..50785c5 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1045,8 +1045,8 @@
}
void InsertCompileOptions(int argc, char** argv) {
- std::ostringstream oss;
if (!avoid_storing_invocation_) {
+ std::ostringstream oss;
for (int i = 0; i < argc; ++i) {
if (i > 0) {
oss << ' ';
@@ -1055,9 +1055,9 @@
}
key_value_store_->Put(OatHeader::kDex2OatCmdLineKey, oss.str());
oss.str(""); // Reset.
+ oss << kRuntimeISA;
+ key_value_store_->Put(OatHeader::kDex2OatHostKey, oss.str());
}
- oss << kRuntimeISA;
- key_value_store_->Put(OatHeader::kDex2OatHostKey, oss.str());
key_value_store_->Put(
OatHeader::kDebuggableKey,
compiler_options_->debuggable_ ? OatHeader::kTrueValue : OatHeader::kFalseValue);
@@ -1513,15 +1513,6 @@
std::vector<gc::space::ImageSpace*> image_spaces =
Runtime::Current()->GetHeap()->GetBootImageSpaces();
image_file_location_oat_checksum_ = image_spaces[0]->GetImageHeader().GetOatChecksum();
- // Store the boot image filename(s).
- std::vector<std::string> image_filenames;
- for (const gc::space::ImageSpace* image_space : image_spaces) {
- image_filenames.push_back(image_space->GetImageFilename());
- }
- std::string image_file_location = android::base::Join(image_filenames, ':');
- if (!image_file_location.empty()) {
- key_value_store_->Put(OatHeader::kImageLocationKey, image_file_location);
- }
} else {
image_file_location_oat_checksum_ = 0u;
}
@@ -1792,14 +1783,14 @@
compiler_options_->no_inline_from_.swap(no_inline_from_dex_files);
}
}
+ compiler_options_->profile_compilation_info_ = profile_compilation_info_.get();
driver_.reset(new CompilerDriver(compiler_options_.get(),
verification_results_.get(),
compiler_kind_,
&compiler_options_->image_classes_,
thread_count_,
- swap_fd_,
- profile_compilation_info_.get()));
+ swap_fd_));
if (!IsBootImage()) {
driver_->SetClasspathDexFiles(class_loader_context_->FlattenOpenedDexFiles());
}
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index 01c24fc..28287bd 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -766,10 +766,6 @@
bss_start_ = (bss_size_ != 0u) ? RoundUp(oat_size_, kPageSize) : 0u;
CHECK_EQ(dex_files_->size(), oat_dex_files_.size());
- if (GetCompilerOptions().IsBootImage()) {
- CHECK_EQ(image_writer_ != nullptr,
- oat_header_->GetStoreValueByKey(OatHeader::kImageLocationKey) == nullptr);
- }
write_state_ = WriteState::kWriteRoData;
}
diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc
index 83fb17c..af02bfc 100644
--- a/dex2oat/linker/oat_writer_test.cc
+++ b/dex2oat/linker/oat_writer_test.cc
@@ -394,7 +394,6 @@
ScratchFile tmp_base, tmp_oat(tmp_base, ".oat"), tmp_vdex(tmp_base, ".vdex");
SafeMap<std::string, std::string> key_value_store;
- key_value_store.Put(OatHeader::kImageLocationKey, "lue.art");
bool success = WriteElf(tmp_vdex.GetFile(),
tmp_oat.GetFile(),
class_linker->GetBootClassPath(),
@@ -418,7 +417,6 @@
ASSERT_TRUE(oat_header.IsValid());
ASSERT_EQ(class_linker->GetBootClassPath().size(), oat_header.GetDexFileCount()); // core
ASSERT_EQ(42U, oat_header.GetImageFileLocationOatChecksum());
- ASSERT_EQ("lue.art", std::string(oat_header.GetStoreValueByKey(OatHeader::kImageLocationKey)));
ASSERT_TRUE(java_lang_dex_file_ != nullptr);
const DexFile& dex_file = *java_lang_dex_file_;
@@ -517,7 +515,6 @@
ScratchFile tmp_base, tmp_oat(tmp_base, ".oat"), tmp_vdex(tmp_base, ".vdex");
SafeMap<std::string, std::string> key_value_store;
- key_value_store.Put(OatHeader::kImageLocationKey, "test.art");
bool success = WriteElf(tmp_vdex.GetFile(),
tmp_oat.GetFile(),
dex_files,
@@ -584,7 +581,6 @@
ScratchFile tmp_base, tmp_oat(tmp_base, ".oat"), tmp_vdex(tmp_base, ".vdex");
SafeMap<std::string, std::string> key_value_store;
- key_value_store.Put(OatHeader::kImageLocationKey, "test.art");
std::unique_ptr<ProfileCompilationInfo>
profile_compilation_info(use_profile ? new ProfileCompilationInfo() : nullptr);
success = WriteElf(tmp_vdex.GetFile(),
@@ -714,7 +710,6 @@
ASSERT_TRUE(success) << strerror(errno);
SafeMap<std::string, std::string> key_value_store;
- key_value_store.Put(OatHeader::kImageLocationKey, "test.art");
{
// Test using the AddDexFileSource() interface with the zip file.
std::vector<const char*> input_filenames = { zip_file.GetFilename().c_str() };
@@ -831,7 +826,6 @@
ASSERT_TRUE(success) << strerror(errno);
SafeMap<std::string, std::string> key_value_store;
- key_value_store.Put(OatHeader::kImageLocationKey, "test.art");
std::vector<const char*> input_filenames = { zip_file.GetFilename().c_str() };
ScratchFile oat_file, vdex_file(oat_file, ".vdex");
std::unique_ptr<ProfileCompilationInfo> profile_compilation_info(new ProfileCompilationInfo());
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index d1d5bc4..67513f9 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -965,9 +965,6 @@
runtime->GetOatFileManager().RegisterImageOatFiles(spaces);
DCHECK(!oat_files.empty());
const OatHeader& default_oat_header = oat_files[0]->GetOatHeader();
- const char* image_file_location = oat_files[0]->GetOatHeader().
- GetStoreValueByKey(OatHeader::kImageLocationKey);
- CHECK(image_file_location == nullptr || *image_file_location == 0);
quick_resolution_trampoline_ = default_oat_header.GetQuickResolutionTrampoline();
quick_imt_conflict_trampoline_ = default_oat_header.GetQuickImtConflictTrampoline();
quick_generic_jni_trampoline_ = default_oat_header.GetQuickGenericJniTrampoline();
diff --git a/runtime/interpreter/interpreter_switch_impl-inl.h b/runtime/interpreter/interpreter_switch_impl-inl.h
index 71b2336..4125a0a 100644
--- a/runtime/interpreter/interpreter_switch_impl-inl.h
+++ b/runtime/interpreter/interpreter_switch_impl-inl.h
@@ -37,339 +37,373 @@
namespace art {
namespace interpreter {
-// TODO: Replace macros with member functions.
-#define CHECK_FORCE_RETURN() \
- { \
- if (UNLIKELY(shadow_frame.GetForcePopFrame())) { \
- DCHECK(PrevFrameWillRetry(self, shadow_frame)) \
- << "Pop frame forced without previous frame ready to retry instruction!"; \
- DCHECK(Runtime::Current()->AreNonStandardExitsEnabled()); \
- if (UNLIKELY(NeedsMethodExitEvent(instrumentation))) { \
- SendMethodExitEvents(self, \
- instrumentation, \
- shadow_frame, \
- shadow_frame.GetThisObject(Accessor().InsSize()), \
- shadow_frame.GetMethod(), \
- inst->GetDexPc(Insns()), \
- JValue()); \
- } \
- ctx->result = JValue(); /* Handled in caller. */ \
- exit_interpreter_loop = true; \
- return; \
- } \
- } \
- do {} while (false)
-
-#define HANDLE_PENDING_EXCEPTION_WITH_INSTRUMENTATION(instr) \
- { \
- DCHECK(self->IsExceptionPending()); \
- self->AllowThreadSuspension(); \
- CHECK_FORCE_RETURN(); \
- if (!MoveToExceptionHandler(self, shadow_frame, instr)) { \
- /* Structured locking is to be enforced for abnormal termination, too. */ \
- DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame); \
- if (ctx->interpret_one_instruction) { \
- /* Signal mterp to return to caller */ \
- shadow_frame.SetDexPC(dex::kDexNoIndex); \
- } \
- ctx->result = JValue(); /* Handled in caller. */ \
- exit_interpreter_loop = true; \
- return; \
- } else { \
- CHECK_FORCE_RETURN(); \
- int32_t displacement = \
- static_cast<int32_t>(shadow_frame.GetDexPC()) - static_cast<int32_t>(dex_pc); \
- inst = inst->RelativeAt(displacement); \
- return; /* Stop executing this opcode and continue in the exception handler. */ \
- } \
- } \
- 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) \
- { \
- 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. */ \
- DCHECK(inst->IsInvoke()); \
- shadow_frame.SetForceRetryInstruction(false); \
- if (UNLIKELY(_is_exception_pending)) { \
- DCHECK(self->IsExceptionPending()); \
- if (kIsDebugBuild) { \
- LOG(WARNING) << "Suppressing exception for instruction-retry: " \
- << self->GetException()->Dump(); \
- } \
- self->ClearException(); \
- } \
- } else if (UNLIKELY(_is_exception_pending)) { \
- /* Should have succeeded. */ \
- DCHECK(!shadow_frame.GetForceRetryInstruction()); \
- HANDLE_PENDING_EXCEPTION(); \
- } else { \
- inst = inst->_next_function(); \
- } \
- } \
- 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)
-#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(_is_exception_pending) \
- POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_IMPL(_is_exception_pending, Next_3xx)
-
-#define POSSIBLY_HANDLE_PENDING_EXCEPTION(_is_exception_pending, _next_function) \
- { \
- /* Should only be on invoke instructions. */ \
- DCHECK(!shadow_frame.GetForceRetryInstruction()); \
- if (UNLIKELY(_is_exception_pending)) { \
- HANDLE_PENDING_EXCEPTION(); \
- } else { \
- inst = inst->_next_function(); \
- } \
- } \
- do {} while (false)
-
-#define HANDLE_MONITOR_CHECKS() \
- if (!DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame)) { \
- HANDLE_PENDING_EXCEPTION(); \
- }
-
-// Code to run before each dex instruction.
-#define PREAMBLE_SAVE(save_ref) \
- { \
- /* We need to put this before & after the instrumentation to avoid having to put in a */ \
- /* post-script macro. */ \
- CHECK_FORCE_RETURN(); \
- if (UNLIKELY(instrumentation->HasDexPcListeners())) { \
- if (UNLIKELY(!DoDexPcMoveEvent(self, \
- Accessor(), \
- shadow_frame, \
- dex_pc, \
- instrumentation, \
- save_ref))) { \
- HANDLE_PENDING_EXCEPTION(); \
- } \
- CHECK_FORCE_RETURN(); \
- } \
- } \
- do {} while (false)
-
-#define PREAMBLE() PREAMBLE_SAVE(nullptr)
-
-#define BRANCH_INSTRUMENTATION(offset) \
- { \
- if (UNLIKELY(instrumentation->HasBranchListeners())) { \
- instrumentation->Branch(self, shadow_frame.GetMethod(), dex_pc, offset); \
- } \
- JValue result; \
- if (jit::Jit::MaybeDoOnStackReplacement(self, \
- shadow_frame.GetMethod(), \
- dex_pc, \
- offset, \
- &result)) { \
- if (ctx->interpret_one_instruction) { \
- /* OSR has completed execution of the method. Signal mterp to return to caller */ \
- shadow_frame.SetDexPC(dex::kDexNoIndex); \
- } \
- ctx->result = result; \
- exit_interpreter_loop = true; \
- return; \
- } \
- } \
- do {} while (false)
-
-#define HOTNESS_UPDATE() \
- { \
- jit::Jit* jit = Runtime::Current()->GetJit(); \
- if (jit != nullptr) { \
- jit->AddSamples(self, shadow_frame.GetMethod(), 1, /*with_backedges=*/ true); \
- } \
- } \
- do {} while (false)
-
-#define HANDLE_ASYNC_EXCEPTION() \
- if (UNLIKELY(self->ObserveAsyncException())) { \
- HANDLE_PENDING_EXCEPTION(); \
- } \
- do {} while (false)
-
-#define HANDLE_BACKWARD_BRANCH(offset) \
- { \
- 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(); \
- } \
- } \
- 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
-// to detect exceptions thrown by the DexPcMovedEvent itself. These exceptions could be thrown by
-// jvmti-agents while handling breakpoint or single step events. We had to move this into its own
-// function because it was making ExecuteSwitchImpl have too large a stack.
-NO_INLINE static bool DoDexPcMoveEvent(Thread* self,
- const CodeItemDataAccessor& accessor,
- const ShadowFrame& shadow_frame,
- uint32_t dex_pc,
- const instrumentation::Instrumentation* instrumentation,
- JValue* save_ref)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- DCHECK(instrumentation->HasDexPcListeners());
- StackHandleScope<2> hs(self);
- Handle<mirror::Throwable> thr(hs.NewHandle(self->GetException()));
- mirror::Object* null_obj = nullptr;
- HandleWrapper<mirror::Object> h(
- hs.NewHandleWrapper(LIKELY(save_ref == nullptr) ? &null_obj : save_ref->GetGCRoot()));
- self->ClearException();
- instrumentation->DexPcMovedEvent(self,
- shadow_frame.GetThisObject(accessor.InsSize()),
- shadow_frame.GetMethod(),
- dex_pc);
- if (UNLIKELY(self->IsExceptionPending())) {
- // We got a new exception in the dex-pc-moved event. We just let this exception replace the old
- // one.
- // TODO It would be good to add the old exception to the suppressed exceptions of the new one if
- // possible.
- return false;
- } else {
- if (UNLIKELY(!thr.IsNull())) {
- self->SetException(thr.Get());
- }
- return true;
- }
-}
-
-static bool NeedsMethodExitEvent(const instrumentation::Instrumentation* ins)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- return ins->HasMethodExitListeners() || ins->HasWatchedFramePopListeners();
-}
-
-// Sends the normal method exit event. Returns true if the events succeeded and false if there is a
-// pending exception.
-NO_INLINE static bool SendMethodExitEvents(Thread* self,
- const instrumentation::Instrumentation* instrumentation,
- const ShadowFrame& frame,
- ObjPtr<mirror::Object> thiz,
- ArtMethod* method,
- uint32_t dex_pc,
- const JValue& result)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- bool had_event = false;
- // We don't send method-exit if it's a pop-frame. We still send frame_popped though.
- if (UNLIKELY(instrumentation->HasMethodExitListeners() && !frame.GetForcePopFrame())) {
- had_event = true;
- instrumentation->MethodExitEvent(self, thiz.Ptr(), method, dex_pc, result);
- }
- if (UNLIKELY(frame.NeedsNotifyPop() && instrumentation->HasWatchedFramePopListeners())) {
- had_event = true;
- instrumentation->WatchedFramePopped(self, frame);
- }
- if (UNLIKELY(had_event)) {
- return !self->IsExceptionPending();
- } else {
- return true;
- }
-}
-
// Short-lived helper class which executes single DEX bytecode. It is inlined by compiler.
//
// The function names must match the names from dex_instruction_list.h and have no arguments.
//
// Any relevant execution information is stored in the fields - it should be kept to minimum.
//
+// Helper methods may return boolean value - in which case 'false' always means
+// "stop executing current opcode" (which does not necessarily exit the interpreter loop).
+//
template<bool do_access_check, bool transaction_active>
class InstructionHandler {
public:
+ ALWAYS_INLINE WARN_UNUSED bool CheckForceReturn()
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (UNLIKELY(shadow_frame.GetForcePopFrame())) {
+ DCHECK(PrevFrameWillRetry(self, shadow_frame))
+ << "Pop frame forced without previous frame ready to retry instruction!";
+ DCHECK(Runtime::Current()->AreNonStandardExitsEnabled());
+ if (UNLIKELY(NeedsMethodExitEvent(instrumentation))) {
+ SendMethodExitEvents(self,
+ instrumentation,
+ shadow_frame,
+ shadow_frame.GetThisObject(Accessor().InsSize()),
+ shadow_frame.GetMethod(),
+ inst->GetDexPc(Insns()),
+ JValue());
+ }
+ ctx->result = JValue(); /* Handled in caller. */
+ exit_interpreter_loop = true;
+ return false;
+ }
+ return true;
+ }
+
+ ALWAYS_INLINE WARN_UNUSED bool HandlePendingExceptionWithInstrumentation(
+ const instrumentation::Instrumentation* instr)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ DCHECK(self->IsExceptionPending());
+ self->AllowThreadSuspension();
+ if (!CheckForceReturn()) {
+ return false;
+ }
+ if (!MoveToExceptionHandler(self, shadow_frame, instr)) {
+ /* Structured locking is to be enforced for abnormal termination, too. */
+ DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame);
+ if (ctx->interpret_one_instruction) {
+ /* Signal mterp to return to caller */
+ shadow_frame.SetDexPC(dex::kDexNoIndex);
+ }
+ ctx->result = JValue(); /* Handled in caller. */
+ exit_interpreter_loop = true;
+ return false; // Return to caller.
+ }
+ if (!CheckForceReturn()) {
+ return false;
+ }
+ int32_t displacement =
+ static_cast<int32_t>(shadow_frame.GetDexPC()) - static_cast<int32_t>(dex_pc);
+ inst = inst->RelativeAt(displacement);
+ return false; // Stop executing this opcode and continue in the exception handler.
+ }
+
+ ALWAYS_INLINE WARN_UNUSED bool HandlePendingException()
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return HandlePendingExceptionWithInstrumentation(instrumentation);
+ }
+
+ ALWAYS_INLINE WARN_UNUSED bool PossiblyHandlePendingExceptionOnInvokeImpl(
+ bool is_exception_pending,
+ const Instruction* next_inst)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ 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. */
+ DCHECK(inst->IsInvoke());
+ shadow_frame.SetForceRetryInstruction(false);
+ if (UNLIKELY(is_exception_pending)) {
+ DCHECK(self->IsExceptionPending());
+ if (kIsDebugBuild) {
+ LOG(WARNING) << "Suppressing exception for instruction-retry: "
+ << self->GetException()->Dump();
+ }
+ self->ClearException();
+ }
+ } else if (UNLIKELY(is_exception_pending)) {
+ /* Should have succeeded. */
+ DCHECK(!shadow_frame.GetForceRetryInstruction());
+ if (!HandlePendingException()) {
+ return false;
+ }
+ } else {
+ inst = next_inst;
+ }
+ return true;
+ }
+
+ ALWAYS_INLINE WARN_UNUSED bool PossiblyHandlePendingException(
+ bool is_exception_pending,
+ const Instruction* next_inst)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ /* Should only be on invoke instructions. */
+ DCHECK(!shadow_frame.GetForceRetryInstruction());
+ if (UNLIKELY(is_exception_pending)) {
+ if (!HandlePendingException()) {
+ return false;
+ }
+ } else {
+ inst = next_inst;
+ }
+ return true;
+ }
+
+ ALWAYS_INLINE WARN_UNUSED bool HandleMonitorChecks()
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (!DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame)) {
+ if (!HandlePendingException()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // Code to run before each dex instruction.
+ ALWAYS_INLINE WARN_UNUSED bool PreambleSave(JValue* save_ref)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ /* We need to put this before & after the instrumentation to avoid having to put in a */
+ /* post-script macro. */
+ if (!CheckForceReturn()) {
+ return false;
+ }
+ if (UNLIKELY(instrumentation->HasDexPcListeners())) {
+ if (UNLIKELY(!DoDexPcMoveEvent(self,
+ Accessor(),
+ shadow_frame,
+ dex_pc,
+ instrumentation,
+ save_ref))) {
+ if (!HandlePendingException()) {
+ return false;
+ }
+ }
+ if (!CheckForceReturn()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ ALWAYS_INLINE WARN_UNUSED bool BranchInstrumentation(int32_t offset)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (UNLIKELY(instrumentation->HasBranchListeners())) {
+ instrumentation->Branch(self, shadow_frame.GetMethod(), dex_pc, offset);
+ }
+ JValue result;
+ if (jit::Jit::MaybeDoOnStackReplacement(self,
+ shadow_frame.GetMethod(),
+ dex_pc,
+ offset,
+ &result)) {
+ if (ctx->interpret_one_instruction) {
+ /* OSR has completed execution of the method. Signal mterp to return to caller */
+ shadow_frame.SetDexPC(dex::kDexNoIndex);
+ }
+ ctx->result = result;
+ exit_interpreter_loop = true;
+ return false;
+ }
+ return true;
+ }
+
+ ALWAYS_INLINE void HotnessUpdate()
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ jit::Jit* jit = Runtime::Current()->GetJit();
+ if (jit != nullptr) {
+ jit->AddSamples(self, shadow_frame.GetMethod(), 1, /*with_backedges=*/ true);
+ }
+ }
+
+ ALWAYS_INLINE WARN_UNUSED bool HandleAsyncException()
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (UNLIKELY(self->ObserveAsyncException())) {
+ if (!HandlePendingException()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ ALWAYS_INLINE void HandleBackwardBranch(int32_t offset)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (IsBackwardBranch(offset)) {
+ HotnessUpdate();
+ /* Record new dex pc early to have consistent suspend point at loop header. */
+ shadow_frame.SetDexPC(inst->GetDexPc(Insns()));
+ self->AllowThreadSuspension();
+ }
+ }
+
+ // 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
+ // to detect exceptions thrown by the DexPcMovedEvent itself. These exceptions could be thrown by
+ // jvmti-agents while handling breakpoint or single step events. We had to move this into its own
+ // function because it was making ExecuteSwitchImpl have too large a stack.
+ NO_INLINE static bool DoDexPcMoveEvent(Thread* self,
+ const CodeItemDataAccessor& accessor,
+ const ShadowFrame& shadow_frame,
+ uint32_t dex_pc,
+ const instrumentation::Instrumentation* instrumentation,
+ JValue* save_ref)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ DCHECK(instrumentation->HasDexPcListeners());
+ StackHandleScope<2> hs(self);
+ Handle<mirror::Throwable> thr(hs.NewHandle(self->GetException()));
+ mirror::Object* null_obj = nullptr;
+ HandleWrapper<mirror::Object> h(
+ hs.NewHandleWrapper(LIKELY(save_ref == nullptr) ? &null_obj : save_ref->GetGCRoot()));
+ self->ClearException();
+ instrumentation->DexPcMovedEvent(self,
+ shadow_frame.GetThisObject(accessor.InsSize()),
+ shadow_frame.GetMethod(),
+ dex_pc);
+ if (UNLIKELY(self->IsExceptionPending())) {
+ // We got a new exception in the dex-pc-moved event.
+ // We just let this exception replace the old one.
+ // TODO It would be good to add the old exception to the
+ // suppressed exceptions of the new one if possible.
+ return false;
+ } else {
+ if (UNLIKELY(!thr.IsNull())) {
+ self->SetException(thr.Get());
+ }
+ return true;
+ }
+ }
+
+ static bool NeedsMethodExitEvent(const instrumentation::Instrumentation* ins)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return ins->HasMethodExitListeners() || ins->HasWatchedFramePopListeners();
+ }
+
+ // Sends the normal method exit event.
+ // Returns true if the events succeeded and false if there is a pending exception.
+ NO_INLINE static bool SendMethodExitEvents(
+ Thread* self,
+ const instrumentation::Instrumentation* instrumentation,
+ const ShadowFrame& frame,
+ ObjPtr<mirror::Object> thiz,
+ ArtMethod* method,
+ uint32_t dex_pc,
+ const JValue& result)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ bool had_event = false;
+ // We don't send method-exit if it's a pop-frame. We still send frame_popped though.
+ if (UNLIKELY(instrumentation->HasMethodExitListeners() && !frame.GetForcePopFrame())) {
+ had_event = true;
+ instrumentation->MethodExitEvent(self, thiz.Ptr(), method, dex_pc, result);
+ }
+ if (UNLIKELY(frame.NeedsNotifyPop() && instrumentation->HasWatchedFramePopListeners())) {
+ had_event = true;
+ instrumentation->WatchedFramePopped(self, frame);
+ }
+ if (UNLIKELY(had_event)) {
+ return !self->IsExceptionPending();
+ } else {
+ return true;
+ }
+ }
+
+#define BRANCH_INSTRUMENTATION(offset) \
+ if (!BranchInstrumentation(offset)) { \
+ return; \
+ }
+
+#define HANDLE_PENDING_EXCEPTION() \
+ if (!HandlePendingException()) { \
+ return; \
+ }
+
+#define POSSIBLY_HANDLE_PENDING_EXCEPTION(is_exception_pending, next_function) \
+ if (!PossiblyHandlePendingException(is_exception_pending, inst->next_function())) { \
+ return; \
+ }
+
+#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(is_exception_pending) \
+ if (!PossiblyHandlePendingExceptionOnInvokeImpl(is_exception_pending, inst->Next_4xx())) { \
+ return; \
+ }
+
+#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(is_exception_pending) \
+ if (!PossiblyHandlePendingExceptionOnInvokeImpl(is_exception_pending, inst->Next_3xx())) { \
+ return; \
+ }
+
ALWAYS_INLINE void NOP() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
inst = inst->Next_1xx();
}
ALWAYS_INLINE void MOVE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_12x(inst_data),
shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
inst = inst->Next_1xx();
}
ALWAYS_INLINE void MOVE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_22x(inst_data),
shadow_frame.GetVReg(inst->VRegB_22x()));
inst = inst->Next_2xx();
}
ALWAYS_INLINE void MOVE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_32x(),
shadow_frame.GetVReg(inst->VRegB_32x()));
inst = inst->Next_3xx();
}
ALWAYS_INLINE void MOVE_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data),
shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
inst = inst->Next_1xx();
}
ALWAYS_INLINE void MOVE_WIDE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegLong(inst->VRegA_22x(inst_data),
shadow_frame.GetVRegLong(inst->VRegB_22x()));
inst = inst->Next_2xx();
}
ALWAYS_INLINE void MOVE_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegLong(inst->VRegA_32x(),
shadow_frame.GetVRegLong(inst->VRegB_32x()));
inst = inst->Next_3xx();
}
ALWAYS_INLINE void MOVE_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegReference(inst->VRegA_12x(inst_data),
shadow_frame.GetVRegReference(inst->VRegB_12x(inst_data)));
inst = inst->Next_1xx();
}
ALWAYS_INLINE void MOVE_OBJECT_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegReference(inst->VRegA_22x(inst_data),
shadow_frame.GetVRegReference(inst->VRegB_22x()));
inst = inst->Next_2xx();
}
ALWAYS_INLINE void MOVE_OBJECT_16() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegReference(inst->VRegA_32x(),
shadow_frame.GetVRegReference(inst->VRegB_32x()));
inst = inst->Next_3xx();
}
ALWAYS_INLINE void MOVE_RESULT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_11x(inst_data), ResultRegister()->GetI());
inst = inst->Next_1xx();
}
ALWAYS_INLINE void MOVE_RESULT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegLong(inst->VRegA_11x(inst_data), ResultRegister()->GetJ());
inst = inst->Next_1xx();
}
ALWAYS_INLINE void MOVE_RESULT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE_SAVE(ResultRegister());
shadow_frame.SetVRegReference(inst->VRegA_11x(inst_data), ResultRegister()->GetL());
inst = inst->Next_1xx();
}
ALWAYS_INLINE void MOVE_EXCEPTION() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::Throwable> exception = self->GetException();
DCHECK(exception != nullptr) << "No pending exception on MOVE_EXCEPTION instruction";
shadow_frame.SetVRegReference(inst->VRegA_11x(inst_data), exception);
@@ -378,10 +412,11 @@
}
ALWAYS_INLINE void RETURN_VOID_NO_BARRIER() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
JValue result;
self->AllowThreadSuspension();
- HANDLE_MONITOR_CHECKS();
+ if (!HandleMonitorChecks()) {
+ return;
+ }
if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
!SendMethodExitEvents(self,
instrumentation,
@@ -390,7 +425,9 @@
shadow_frame.GetMethod(),
inst->GetDexPc(Insns()),
result))) {
- HANDLE_PENDING_EXCEPTION_WITH_INSTRUMENTATION(nullptr);
+ if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
+ return;
+ }
}
if (ctx->interpret_one_instruction) {
/* Signal mterp to return to caller */
@@ -401,11 +438,12 @@
}
ALWAYS_INLINE void RETURN_VOID() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
QuasiAtomic::ThreadFenceForConstructor();
JValue result;
self->AllowThreadSuspension();
- HANDLE_MONITOR_CHECKS();
+ if (!HandleMonitorChecks()) {
+ return;
+ }
if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
!SendMethodExitEvents(self,
instrumentation,
@@ -414,7 +452,9 @@
shadow_frame.GetMethod(),
inst->GetDexPc(Insns()),
result))) {
- HANDLE_PENDING_EXCEPTION_WITH_INSTRUMENTATION(nullptr);
+ if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
+ return;
+ }
}
if (ctx->interpret_one_instruction) {
/* Signal mterp to return to caller */
@@ -425,12 +465,13 @@
}
ALWAYS_INLINE void RETURN() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
JValue result;
result.SetJ(0);
result.SetI(shadow_frame.GetVReg(inst->VRegA_11x(inst_data)));
self->AllowThreadSuspension();
- HANDLE_MONITOR_CHECKS();
+ if (!HandleMonitorChecks()) {
+ return;
+ }
if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
!SendMethodExitEvents(self,
instrumentation,
@@ -439,7 +480,9 @@
shadow_frame.GetMethod(),
inst->GetDexPc(Insns()),
result))) {
- HANDLE_PENDING_EXCEPTION_WITH_INSTRUMENTATION(nullptr);
+ if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
+ return;
+ }
}
if (ctx->interpret_one_instruction) {
/* Signal mterp to return to caller */
@@ -450,11 +493,12 @@
}
ALWAYS_INLINE void RETURN_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
JValue result;
result.SetJ(shadow_frame.GetVRegLong(inst->VRegA_11x(inst_data)));
self->AllowThreadSuspension();
- HANDLE_MONITOR_CHECKS();
+ if (!HandleMonitorChecks()) {
+ return;
+ }
if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
!SendMethodExitEvents(self,
instrumentation,
@@ -463,7 +507,9 @@
shadow_frame.GetMethod(),
inst->GetDexPc(Insns()),
result))) {
- HANDLE_PENDING_EXCEPTION_WITH_INSTRUMENTATION(nullptr);
+ if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
+ return;
+ }
}
if (ctx->interpret_one_instruction) {
/* Signal mterp to return to caller */
@@ -474,10 +520,11 @@
}
ALWAYS_INLINE void RETURN_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
JValue result;
self->AllowThreadSuspension();
- HANDLE_MONITOR_CHECKS();
+ if (!HandleMonitorChecks()) {
+ return;
+ }
const size_t ref_idx = inst->VRegA_11x(inst_data);
ObjPtr<mirror::Object> obj_result = shadow_frame.GetVRegReference(ref_idx);
if (do_assignability_check && obj_result != nullptr) {
@@ -507,7 +554,9 @@
shadow_frame.GetMethod(),
inst->GetDexPc(Insns()),
result))) {
- HANDLE_PENDING_EXCEPTION_WITH_INSTRUMENTATION(nullptr);
+ if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
+ return;
+ }
}
// Re-load since it might have moved during the MethodExitEvent.
result.SetL(shadow_frame.GetVRegReference(ref_idx));
@@ -520,7 +569,6 @@
}
ALWAYS_INLINE void CONST_4() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t dst = inst->VRegA_11n(inst_data);
int4_t val = inst->VRegB_11n(inst_data);
shadow_frame.SetVReg(dst, val);
@@ -531,7 +579,6 @@
}
ALWAYS_INLINE void CONST_16() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint8_t dst = inst->VRegA_21s(inst_data);
int16_t val = inst->VRegB_21s();
shadow_frame.SetVReg(dst, val);
@@ -542,7 +589,6 @@
}
ALWAYS_INLINE void CONST() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint8_t dst = inst->VRegA_31i(inst_data);
int32_t val = inst->VRegB_31i();
shadow_frame.SetVReg(dst, val);
@@ -553,7 +599,6 @@
}
ALWAYS_INLINE void CONST_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint8_t dst = inst->VRegA_21h(inst_data);
int32_t val = static_cast<int32_t>(inst->VRegB_21h() << 16);
shadow_frame.SetVReg(dst, val);
@@ -564,32 +609,27 @@
}
ALWAYS_INLINE void CONST_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegLong(inst->VRegA_21s(inst_data), inst->VRegB_21s());
inst = inst->Next_2xx();
}
ALWAYS_INLINE void CONST_WIDE_32() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegLong(inst->VRegA_31i(inst_data), inst->VRegB_31i());
inst = inst->Next_3xx();
}
ALWAYS_INLINE void CONST_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegLong(inst->VRegA_51l(inst_data), inst->VRegB_51l());
inst = inst->Next_51l();
}
ALWAYS_INLINE void CONST_WIDE_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegLong(inst->VRegA_21h(inst_data),
static_cast<uint64_t>(inst->VRegB_21h()) << 48);
inst = inst->Next_2xx();
}
ALWAYS_INLINE void CONST_STRING() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::String> s = ResolveString(self,
shadow_frame,
dex::StringIndex(inst->VRegB_21c()));
@@ -602,7 +642,6 @@
}
ALWAYS_INLINE void CONST_STRING_JUMBO() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::String> s = ResolveString(self,
shadow_frame,
dex::StringIndex(inst->VRegB_31c()));
@@ -615,7 +654,6 @@
}
ALWAYS_INLINE void CONST_CLASS() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegB_21c()),
shadow_frame.GetMethod(),
self,
@@ -630,7 +668,6 @@
}
ALWAYS_INLINE void CONST_METHOD_HANDLE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ClassLinker* cl = Runtime::Current()->GetClassLinker();
ObjPtr<mirror::MethodHandle> mh = cl->ResolveMethodHandle(self,
inst->VRegB_21c(),
@@ -644,7 +681,6 @@
}
ALWAYS_INLINE void CONST_METHOD_TYPE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ClassLinker* cl = Runtime::Current()->GetClassLinker();
ObjPtr<mirror::MethodType> mt = cl->ResolveMethodType(self,
dex::ProtoIndex(inst->VRegB_21c()),
@@ -658,8 +694,9 @@
}
ALWAYS_INLINE void MONITOR_ENTER() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
- HANDLE_ASYNC_EXCEPTION();
+ if (!HandleAsyncException()) {
+ return;
+ }
ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
if (UNLIKELY(obj == nullptr)) {
ThrowNullPointerExceptionFromInterpreter();
@@ -671,8 +708,9 @@
}
ALWAYS_INLINE void MONITOR_EXIT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
- HANDLE_ASYNC_EXCEPTION();
+ if (!HandleAsyncException()) {
+ return;
+ }
ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
if (UNLIKELY(obj == nullptr)) {
ThrowNullPointerExceptionFromInterpreter();
@@ -684,7 +722,6 @@
}
ALWAYS_INLINE void CHECK_CAST() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegB_21c()),
shadow_frame.GetMethod(),
self,
@@ -704,7 +741,6 @@
}
ALWAYS_INLINE void INSTANCE_OF() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegC_22c()),
shadow_frame.GetMethod(),
self,
@@ -721,7 +757,6 @@
}
ALWAYS_INLINE void ARRAY_LENGTH() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::Object> array = shadow_frame.GetVRegReference(inst->VRegB_12x(inst_data));
if (UNLIKELY(array == nullptr)) {
ThrowNullPointerExceptionFromInterpreter();
@@ -733,7 +768,6 @@
}
ALWAYS_INLINE void NEW_INSTANCE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::Object> obj = nullptr;
ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegB_21c()),
shadow_frame.GetMethod(),
@@ -768,7 +802,6 @@
}
ALWAYS_INLINE void NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
int32_t length = shadow_frame.GetVReg(inst->VRegB_22c(inst_data));
ObjPtr<mirror::Object> obj = AllocArrayFromCode<do_access_check, true>(
dex::TypeIndex(inst->VRegC_22c()),
@@ -785,7 +818,6 @@
}
ALWAYS_INLINE void FILLED_NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success =
DoFilledNewArray<false, do_access_check, transaction_active>(inst, shadow_frame, self,
ResultRegister());
@@ -793,7 +825,6 @@
}
ALWAYS_INLINE void FILLED_NEW_ARRAY_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success =
DoFilledNewArray<true, do_access_check, transaction_active>(inst, shadow_frame,
self, ResultRegister());
@@ -801,7 +832,6 @@
}
ALWAYS_INLINE void FILL_ARRAY_DATA() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
const Instruction::ArrayDataPayload* payload =
reinterpret_cast<const Instruction::ArrayDataPayload*>(payload_addr);
@@ -817,8 +847,9 @@
}
ALWAYS_INLINE void THROW() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
- HANDLE_ASYNC_EXCEPTION();
+ if (!HandleAsyncException()) {
+ return;
+ }
ObjPtr<mirror::Object> exception =
shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
if (UNLIKELY(exception == nullptr)) {
@@ -836,46 +867,47 @@
}
ALWAYS_INLINE void GOTO() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
- HANDLE_ASYNC_EXCEPTION();
+ if (!HandleAsyncException()) {
+ return;
+ }
int8_t offset = inst->VRegA_10t(inst_data);
BRANCH_INSTRUMENTATION(offset);
inst = inst->RelativeAt(offset);
- HANDLE_BACKWARD_BRANCH(offset);
+ HandleBackwardBranch(offset);
}
ALWAYS_INLINE void GOTO_16() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
- HANDLE_ASYNC_EXCEPTION();
+ if (!HandleAsyncException()) {
+ return;
+ }
int16_t offset = inst->VRegA_20t();
BRANCH_INSTRUMENTATION(offset);
inst = inst->RelativeAt(offset);
- HANDLE_BACKWARD_BRANCH(offset);
+ HandleBackwardBranch(offset);
}
ALWAYS_INLINE void GOTO_32() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
- HANDLE_ASYNC_EXCEPTION();
+ if (!HandleAsyncException()) {
+ return;
+ }
int32_t offset = inst->VRegA_30t();
BRANCH_INSTRUMENTATION(offset);
inst = inst->RelativeAt(offset);
- HANDLE_BACKWARD_BRANCH(offset);
+ HandleBackwardBranch(offset);
}
ALWAYS_INLINE void PACKED_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
int32_t offset = DoPackedSwitch(inst, shadow_frame, inst_data);
BRANCH_INSTRUMENTATION(offset);
inst = inst->RelativeAt(offset);
- HANDLE_BACKWARD_BRANCH(offset);
+ HandleBackwardBranch(offset);
}
ALWAYS_INLINE void SPARSE_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
int32_t offset = DoSparseSwitch(inst, shadow_frame, inst_data);
BRANCH_INSTRUMENTATION(offset);
inst = inst->RelativeAt(offset);
- HANDLE_BACKWARD_BRANCH(offset);
+ HandleBackwardBranch(offset);
}
#pragma clang diagnostic push
@@ -883,7 +915,6 @@
ALWAYS_INLINE void CMPL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
float val1 = shadow_frame.GetVRegFloat(inst->VRegB_23x());
float val2 = shadow_frame.GetVRegFloat(inst->VRegC_23x());
int32_t result;
@@ -899,7 +930,6 @@
}
ALWAYS_INLINE void CMPG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
float val1 = shadow_frame.GetVRegFloat(inst->VRegB_23x());
float val2 = shadow_frame.GetVRegFloat(inst->VRegC_23x());
int32_t result;
@@ -915,7 +945,6 @@
}
ALWAYS_INLINE void CMPL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
double val1 = shadow_frame.GetVRegDouble(inst->VRegB_23x());
double val2 = shadow_frame.GetVRegDouble(inst->VRegC_23x());
int32_t result;
@@ -932,7 +961,6 @@
ALWAYS_INLINE void CMPG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
double val1 = shadow_frame.GetVRegDouble(inst->VRegB_23x());
double val2 = shadow_frame.GetVRegDouble(inst->VRegC_23x());
int32_t result;
@@ -951,7 +979,6 @@
ALWAYS_INLINE void CMP_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
int64_t val1 = shadow_frame.GetVRegLong(inst->VRegB_23x());
int64_t val2 = shadow_frame.GetVRegLong(inst->VRegC_23x());
int32_t result;
@@ -967,13 +994,12 @@
}
ALWAYS_INLINE void IF_EQ() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) ==
shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
int16_t offset = inst->VRegC_22t();
BRANCH_INSTRUMENTATION(offset);
inst = inst->RelativeAt(offset);
- HANDLE_BACKWARD_BRANCH(offset);
+ HandleBackwardBranch(offset);
} else {
BRANCH_INSTRUMENTATION(2);
inst = inst->Next_2xx();
@@ -981,13 +1007,12 @@
}
ALWAYS_INLINE void IF_NE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) !=
shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
int16_t offset = inst->VRegC_22t();
BRANCH_INSTRUMENTATION(offset);
inst = inst->RelativeAt(offset);
- HANDLE_BACKWARD_BRANCH(offset);
+ HandleBackwardBranch(offset);
} else {
BRANCH_INSTRUMENTATION(2);
inst = inst->Next_2xx();
@@ -995,13 +1020,12 @@
}
ALWAYS_INLINE void IF_LT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) <
shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
int16_t offset = inst->VRegC_22t();
BRANCH_INSTRUMENTATION(offset);
inst = inst->RelativeAt(offset);
- HANDLE_BACKWARD_BRANCH(offset);
+ HandleBackwardBranch(offset);
} else {
BRANCH_INSTRUMENTATION(2);
inst = inst->Next_2xx();
@@ -1009,13 +1033,12 @@
}
ALWAYS_INLINE void IF_GE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) >=
shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
int16_t offset = inst->VRegC_22t();
BRANCH_INSTRUMENTATION(offset);
inst = inst->RelativeAt(offset);
- HANDLE_BACKWARD_BRANCH(offset);
+ HandleBackwardBranch(offset);
} else {
BRANCH_INSTRUMENTATION(2);
inst = inst->Next_2xx();
@@ -1023,13 +1046,12 @@
}
ALWAYS_INLINE void IF_GT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) >
shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
int16_t offset = inst->VRegC_22t();
BRANCH_INSTRUMENTATION(offset);
inst = inst->RelativeAt(offset);
- HANDLE_BACKWARD_BRANCH(offset);
+ HandleBackwardBranch(offset);
} else {
BRANCH_INSTRUMENTATION(2);
inst = inst->Next_2xx();
@@ -1037,13 +1059,12 @@
}
ALWAYS_INLINE void IF_LE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) <=
shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
int16_t offset = inst->VRegC_22t();
BRANCH_INSTRUMENTATION(offset);
inst = inst->RelativeAt(offset);
- HANDLE_BACKWARD_BRANCH(offset);
+ HandleBackwardBranch(offset);
} else {
BRANCH_INSTRUMENTATION(2);
inst = inst->Next_2xx();
@@ -1051,12 +1072,11 @@
}
ALWAYS_INLINE void IF_EQZ() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) == 0) {
int16_t offset = inst->VRegB_21t();
BRANCH_INSTRUMENTATION(offset);
inst = inst->RelativeAt(offset);
- HANDLE_BACKWARD_BRANCH(offset);
+ HandleBackwardBranch(offset);
} else {
BRANCH_INSTRUMENTATION(2);
inst = inst->Next_2xx();
@@ -1064,12 +1084,11 @@
}
ALWAYS_INLINE void IF_NEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) != 0) {
int16_t offset = inst->VRegB_21t();
BRANCH_INSTRUMENTATION(offset);
inst = inst->RelativeAt(offset);
- HANDLE_BACKWARD_BRANCH(offset);
+ HandleBackwardBranch(offset);
} else {
BRANCH_INSTRUMENTATION(2);
inst = inst->Next_2xx();
@@ -1077,12 +1096,11 @@
}
ALWAYS_INLINE void IF_LTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) < 0) {
int16_t offset = inst->VRegB_21t();
BRANCH_INSTRUMENTATION(offset);
inst = inst->RelativeAt(offset);
- HANDLE_BACKWARD_BRANCH(offset);
+ HandleBackwardBranch(offset);
} else {
BRANCH_INSTRUMENTATION(2);
inst = inst->Next_2xx();
@@ -1090,12 +1108,11 @@
}
ALWAYS_INLINE void IF_GEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) >= 0) {
int16_t offset = inst->VRegB_21t();
BRANCH_INSTRUMENTATION(offset);
inst = inst->RelativeAt(offset);
- HANDLE_BACKWARD_BRANCH(offset);
+ HandleBackwardBranch(offset);
} else {
BRANCH_INSTRUMENTATION(2);
inst = inst->Next_2xx();
@@ -1103,12 +1120,11 @@
}
ALWAYS_INLINE void IF_GTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) > 0) {
int16_t offset = inst->VRegB_21t();
BRANCH_INSTRUMENTATION(offset);
inst = inst->RelativeAt(offset);
- HANDLE_BACKWARD_BRANCH(offset);
+ HandleBackwardBranch(offset);
} else {
BRANCH_INSTRUMENTATION(2);
inst = inst->Next_2xx();
@@ -1116,12 +1132,11 @@
}
ALWAYS_INLINE void IF_LEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) <= 0) {
int16_t offset = inst->VRegB_21t();
BRANCH_INSTRUMENTATION(offset);
inst = inst->RelativeAt(offset);
- HANDLE_BACKWARD_BRANCH(offset);
+ HandleBackwardBranch(offset);
} else {
BRANCH_INSTRUMENTATION(2);
inst = inst->Next_2xx();
@@ -1129,7 +1144,6 @@
}
ALWAYS_INLINE void AGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
if (UNLIKELY(a == nullptr)) {
ThrowNullPointerExceptionFromInterpreter();
@@ -1146,7 +1160,6 @@
}
ALWAYS_INLINE void AGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
if (UNLIKELY(a == nullptr)) {
ThrowNullPointerExceptionFromInterpreter();
@@ -1163,7 +1176,6 @@
}
ALWAYS_INLINE void AGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
if (UNLIKELY(a == nullptr)) {
ThrowNullPointerExceptionFromInterpreter();
@@ -1180,7 +1192,6 @@
}
ALWAYS_INLINE void AGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
if (UNLIKELY(a == nullptr)) {
ThrowNullPointerExceptionFromInterpreter();
@@ -1197,7 +1208,6 @@
}
ALWAYS_INLINE void AGET() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
if (UNLIKELY(a == nullptr)) {
ThrowNullPointerExceptionFromInterpreter();
@@ -1215,7 +1225,6 @@
}
ALWAYS_INLINE void AGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
if (UNLIKELY(a == nullptr)) {
ThrowNullPointerExceptionFromInterpreter();
@@ -1233,7 +1242,6 @@
}
ALWAYS_INLINE void AGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
if (UNLIKELY(a == nullptr)) {
ThrowNullPointerExceptionFromInterpreter();
@@ -1250,7 +1258,6 @@
}
ALWAYS_INLINE void APUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
if (UNLIKELY(a == nullptr)) {
ThrowNullPointerExceptionFromInterpreter();
@@ -1268,7 +1275,6 @@
}
ALWAYS_INLINE void APUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
if (UNLIKELY(a == nullptr)) {
ThrowNullPointerExceptionFromInterpreter();
@@ -1286,7 +1292,6 @@
}
ALWAYS_INLINE void APUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
if (UNLIKELY(a == nullptr)) {
ThrowNullPointerExceptionFromInterpreter();
@@ -1304,7 +1309,6 @@
}
ALWAYS_INLINE void APUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
if (UNLIKELY(a == nullptr)) {
ThrowNullPointerExceptionFromInterpreter();
@@ -1322,7 +1326,6 @@
}
ALWAYS_INLINE void APUT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
if (UNLIKELY(a == nullptr)) {
ThrowNullPointerExceptionFromInterpreter();
@@ -1341,7 +1344,6 @@
}
ALWAYS_INLINE void APUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
if (UNLIKELY(a == nullptr)) {
ThrowNullPointerExceptionFromInterpreter();
@@ -1360,7 +1362,6 @@
}
ALWAYS_INLINE void APUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
if (UNLIKELY(a == nullptr)) {
ThrowNullPointerExceptionFromInterpreter();
@@ -1378,378 +1379,323 @@
}
ALWAYS_INLINE void IGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimBoolean, do_access_check>(
self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimByte, do_access_check>(
self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimChar, do_access_check>(
self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimShort, do_access_check>(
self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IGET() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimInt, do_access_check>(
self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimLong, do_access_check>(
self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldGet<InstanceObjectRead, Primitive::kPrimNot, do_access_check>(
self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IGET_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoIGetQuick<Primitive::kPrimInt>(shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IGET_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoIGetQuick<Primitive::kPrimLong>(shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IGET_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoIGetQuick<Primitive::kPrimNot>(shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IGET_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoIGetQuick<Primitive::kPrimBoolean>(shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IGET_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoIGetQuick<Primitive::kPrimByte>(shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IGET_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoIGetQuick<Primitive::kPrimChar>(shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IGET_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoIGetQuick<Primitive::kPrimShort>(shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void SGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimBoolean, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void SGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimByte, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void SGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimChar, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void SGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimShort, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void SGET() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimInt, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void SGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimLong, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void SGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldGet<StaticObjectRead, Primitive::kPrimNot, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimBoolean, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimByte, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimChar, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimShort, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimInt, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimLong, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldPut<InstanceObjectWrite, Primitive::kPrimNot, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IPUT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoIPutQuick<Primitive::kPrimInt, transaction_active>(
shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IPUT_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoIPutQuick<Primitive::kPrimBoolean, transaction_active>(
shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IPUT_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoIPutQuick<Primitive::kPrimByte, transaction_active>(
shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IPUT_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoIPutQuick<Primitive::kPrimChar, transaction_active>(
shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IPUT_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoIPutQuick<Primitive::kPrimShort, transaction_active>(
shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IPUT_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoIPutQuick<Primitive::kPrimLong, transaction_active>(
shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void IPUT_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoIPutQuick<Primitive::kPrimNot, transaction_active>(
shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void SPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimBoolean, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void SPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimByte, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void SPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimChar, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void SPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimShort, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void SPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimInt, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void SPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimLong, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void SPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoFieldPut<StaticObjectWrite, Primitive::kPrimNot, do_access_check,
transaction_active>(self, shadow_frame, inst, inst_data);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void INVOKE_VIRTUAL() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoInvoke<kVirtual, false, do_access_check, /*is_mterp=*/ false>(
self, shadow_frame, inst, inst_data, ResultRegister());
POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
}
ALWAYS_INLINE void INVOKE_VIRTUAL_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoInvoke<kVirtual, true, do_access_check, /*is_mterp=*/ false>(
self, shadow_frame, inst, inst_data, ResultRegister());
POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
}
ALWAYS_INLINE void INVOKE_SUPER() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoInvoke<kSuper, false, do_access_check, /*is_mterp=*/ false>(
self, shadow_frame, inst, inst_data, ResultRegister());
POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
}
ALWAYS_INLINE void INVOKE_SUPER_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoInvoke<kSuper, true, do_access_check, /*is_mterp=*/ false>(
self, shadow_frame, inst, inst_data, ResultRegister());
POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
}
ALWAYS_INLINE void INVOKE_DIRECT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoInvoke<kDirect, false, do_access_check, /*is_mterp=*/ false>(
self, shadow_frame, inst, inst_data, ResultRegister());
POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
}
ALWAYS_INLINE void INVOKE_DIRECT_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoInvoke<kDirect, true, do_access_check, /*is_mterp=*/ false>(
self, shadow_frame, inst, inst_data, ResultRegister());
POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
}
ALWAYS_INLINE void INVOKE_INTERFACE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoInvoke<kInterface, false, do_access_check, /*is_mterp=*/ false>(
self, shadow_frame, inst, inst_data, ResultRegister());
POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
}
ALWAYS_INLINE void INVOKE_INTERFACE_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoInvoke<kInterface, true, do_access_check, /*is_mterp=*/ false>(
self, shadow_frame, inst, inst_data, ResultRegister());
POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
}
ALWAYS_INLINE void INVOKE_STATIC() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoInvoke<kStatic, false, do_access_check, /*is_mterp=*/ false>(
self, shadow_frame, inst, inst_data, ResultRegister());
POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
}
ALWAYS_INLINE void INVOKE_STATIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoInvoke<kStatic, true, do_access_check, /*is_mterp=*/ false>(
self, shadow_frame, inst, inst_data, ResultRegister());
POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
}
ALWAYS_INLINE void INVOKE_VIRTUAL_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoInvoke<kVirtual, false, do_access_check, /*is_mterp=*/ false,
/*is_quick=*/ true>(self, shadow_frame, inst, inst_data, ResultRegister());
POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
}
ALWAYS_INLINE void INVOKE_VIRTUAL_RANGE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoInvoke<kVirtual, true, do_access_check, /*is_mterp=*/ false,
/*is_quick=*/ true>(self, shadow_frame, inst, inst_data, ResultRegister());
POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
}
ALWAYS_INLINE void INVOKE_POLYMORPHIC() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
bool success = DoInvokePolymorphic</* is_range= */ false>(
self, shadow_frame, inst, inst_data, ResultRegister());
@@ -1757,7 +1703,6 @@
}
ALWAYS_INLINE void INVOKE_POLYMORPHIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
bool success = DoInvokePolymorphic</* is_range= */ true>(
self, shadow_frame, inst, inst_data, ResultRegister());
@@ -1765,7 +1710,6 @@
}
ALWAYS_INLINE void INVOKE_CUSTOM() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
bool success = DoInvokeCustom</* is_range= */ false>(
self, shadow_frame, inst, inst_data, ResultRegister());
@@ -1773,7 +1717,6 @@
}
ALWAYS_INLINE void INVOKE_CUSTOM_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
bool success = DoInvokeCustom</* is_range= */ true>(
self, shadow_frame, inst, inst_data, ResultRegister());
@@ -1781,91 +1724,78 @@
}
ALWAYS_INLINE void NEG_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(
inst->VRegA_12x(inst_data), -shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
inst = inst->Next_1xx();
}
ALWAYS_INLINE void NOT_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(
inst->VRegA_12x(inst_data), ~shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
inst = inst->Next_1xx();
}
ALWAYS_INLINE void NEG_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegLong(
inst->VRegA_12x(inst_data), -shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
inst = inst->Next_1xx();
}
ALWAYS_INLINE void NOT_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegLong(
inst->VRegA_12x(inst_data), ~shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
inst = inst->Next_1xx();
}
ALWAYS_INLINE void NEG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegFloat(
inst->VRegA_12x(inst_data), -shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
inst = inst->Next_1xx();
}
ALWAYS_INLINE void NEG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegDouble(
inst->VRegA_12x(inst_data), -shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
inst = inst->Next_1xx();
}
ALWAYS_INLINE void INT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data),
shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
inst = inst->Next_1xx();
}
ALWAYS_INLINE void INT_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data),
shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
inst = inst->Next_1xx();
}
ALWAYS_INLINE void INT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data),
shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
inst = inst->Next_1xx();
}
ALWAYS_INLINE void LONG_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_12x(inst_data),
shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
inst = inst->Next_1xx();
}
ALWAYS_INLINE void LONG_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data),
shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
inst = inst->Next_1xx();
}
ALWAYS_INLINE void LONG_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data),
shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
inst = inst->Next_1xx();
}
ALWAYS_INLINE void FLOAT_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
float val = shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data));
int32_t result = art_float_to_integral<int32_t, float>(val);
shadow_frame.SetVReg(inst->VRegA_12x(inst_data), result);
@@ -1873,7 +1803,6 @@
}
ALWAYS_INLINE void FLOAT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
float val = shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data));
int64_t result = art_float_to_integral<int64_t, float>(val);
shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data), result);
@@ -1881,14 +1810,12 @@
}
ALWAYS_INLINE void FLOAT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data),
shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
inst = inst->Next_1xx();
}
ALWAYS_INLINE void DOUBLE_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
double val = shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data));
int32_t result = art_float_to_integral<int32_t, double>(val);
shadow_frame.SetVReg(inst->VRegA_12x(inst_data), result);
@@ -1896,7 +1823,6 @@
}
ALWAYS_INLINE void DOUBLE_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
double val = shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data));
int64_t result = art_float_to_integral<int64_t, double>(val);
shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data), result);
@@ -1904,35 +1830,30 @@
}
ALWAYS_INLINE void DOUBLE_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data),
shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
inst = inst->Next_1xx();
}
ALWAYS_INLINE void INT_TO_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_12x(inst_data), static_cast<int8_t>(
shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
inst = inst->Next_1xx();
}
ALWAYS_INLINE void INT_TO_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_12x(inst_data), static_cast<uint16_t>(
shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
inst = inst->Next_1xx();
}
ALWAYS_INLINE void INT_TO_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_12x(inst_data), static_cast<int16_t>(
shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
inst = inst->Next_1xx();
}
ALWAYS_INLINE void ADD_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
SafeAdd(shadow_frame.GetVReg(inst->VRegB_23x()),
shadow_frame.GetVReg(inst->VRegC_23x())));
@@ -1940,7 +1861,6 @@
}
ALWAYS_INLINE void SUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
SafeSub(shadow_frame.GetVReg(inst->VRegB_23x()),
shadow_frame.GetVReg(inst->VRegC_23x())));
@@ -1948,7 +1868,6 @@
}
ALWAYS_INLINE void MUL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
SafeMul(shadow_frame.GetVReg(inst->VRegB_23x()),
shadow_frame.GetVReg(inst->VRegC_23x())));
@@ -1956,7 +1875,6 @@
}
ALWAYS_INLINE void DIV_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoIntDivide(shadow_frame, inst->VRegA_23x(inst_data),
shadow_frame.GetVReg(inst->VRegB_23x()),
shadow_frame.GetVReg(inst->VRegC_23x()));
@@ -1964,7 +1882,6 @@
}
ALWAYS_INLINE void REM_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoIntRemainder(shadow_frame, inst->VRegA_23x(inst_data),
shadow_frame.GetVReg(inst->VRegB_23x()),
shadow_frame.GetVReg(inst->VRegC_23x()));
@@ -1972,7 +1889,6 @@
}
ALWAYS_INLINE void SHL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
shadow_frame.GetVReg(inst->VRegB_23x()) <<
(shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
@@ -1980,7 +1896,6 @@
}
ALWAYS_INLINE void SHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
shadow_frame.GetVReg(inst->VRegB_23x()) >>
(shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
@@ -1988,7 +1903,6 @@
}
ALWAYS_INLINE void USHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
static_cast<uint32_t>(shadow_frame.GetVReg(inst->VRegB_23x())) >>
(shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
@@ -1996,7 +1910,6 @@
}
ALWAYS_INLINE void AND_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
shadow_frame.GetVReg(inst->VRegB_23x()) &
shadow_frame.GetVReg(inst->VRegC_23x()));
@@ -2004,7 +1917,6 @@
}
ALWAYS_INLINE void OR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
shadow_frame.GetVReg(inst->VRegB_23x()) |
shadow_frame.GetVReg(inst->VRegC_23x()));
@@ -2012,7 +1924,6 @@
}
ALWAYS_INLINE void XOR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
shadow_frame.GetVReg(inst->VRegB_23x()) ^
shadow_frame.GetVReg(inst->VRegC_23x()));
@@ -2020,7 +1931,6 @@
}
ALWAYS_INLINE void ADD_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
SafeAdd(shadow_frame.GetVRegLong(inst->VRegB_23x()),
shadow_frame.GetVRegLong(inst->VRegC_23x())));
@@ -2028,7 +1938,6 @@
}
ALWAYS_INLINE void SUB_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
SafeSub(shadow_frame.GetVRegLong(inst->VRegB_23x()),
shadow_frame.GetVRegLong(inst->VRegC_23x())));
@@ -2036,7 +1945,6 @@
}
ALWAYS_INLINE void MUL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
SafeMul(shadow_frame.GetVRegLong(inst->VRegB_23x()),
shadow_frame.GetVRegLong(inst->VRegC_23x())));
@@ -2044,7 +1952,6 @@
}
ALWAYS_INLINE void DIV_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
DoLongDivide(shadow_frame, inst->VRegA_23x(inst_data),
shadow_frame.GetVRegLong(inst->VRegB_23x()),
shadow_frame.GetVRegLong(inst->VRegC_23x()));
@@ -2052,7 +1959,6 @@
}
ALWAYS_INLINE void REM_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
DoLongRemainder(shadow_frame, inst->VRegA_23x(inst_data),
shadow_frame.GetVRegLong(inst->VRegB_23x()),
shadow_frame.GetVRegLong(inst->VRegC_23x()));
@@ -2060,7 +1966,6 @@
}
ALWAYS_INLINE void AND_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
shadow_frame.GetVRegLong(inst->VRegB_23x()) &
shadow_frame.GetVRegLong(inst->VRegC_23x()));
@@ -2068,7 +1973,6 @@
}
ALWAYS_INLINE void OR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
shadow_frame.GetVRegLong(inst->VRegB_23x()) |
shadow_frame.GetVRegLong(inst->VRegC_23x()));
@@ -2076,7 +1980,6 @@
}
ALWAYS_INLINE void XOR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
shadow_frame.GetVRegLong(inst->VRegB_23x()) ^
shadow_frame.GetVRegLong(inst->VRegC_23x()));
@@ -2084,7 +1987,6 @@
}
ALWAYS_INLINE void SHL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
shadow_frame.GetVRegLong(inst->VRegB_23x()) <<
(shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
@@ -2092,7 +1994,6 @@
}
ALWAYS_INLINE void SHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
shadow_frame.GetVRegLong(inst->VRegB_23x()) >>
(shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
@@ -2100,7 +2001,6 @@
}
ALWAYS_INLINE void USHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
static_cast<uint64_t>(shadow_frame.GetVRegLong(inst->VRegB_23x())) >>
(shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
@@ -2108,7 +2008,6 @@
}
ALWAYS_INLINE void ADD_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
shadow_frame.GetVRegFloat(inst->VRegB_23x()) +
shadow_frame.GetVRegFloat(inst->VRegC_23x()));
@@ -2116,7 +2015,6 @@
}
ALWAYS_INLINE void SUB_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
shadow_frame.GetVRegFloat(inst->VRegB_23x()) -
shadow_frame.GetVRegFloat(inst->VRegC_23x()));
@@ -2124,7 +2022,6 @@
}
ALWAYS_INLINE void MUL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
shadow_frame.GetVRegFloat(inst->VRegB_23x()) *
shadow_frame.GetVRegFloat(inst->VRegC_23x()));
@@ -2132,7 +2029,6 @@
}
ALWAYS_INLINE void DIV_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
shadow_frame.GetVRegFloat(inst->VRegB_23x()) /
shadow_frame.GetVRegFloat(inst->VRegC_23x()));
@@ -2140,7 +2036,6 @@
}
ALWAYS_INLINE void REM_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
fmodf(shadow_frame.GetVRegFloat(inst->VRegB_23x()),
shadow_frame.GetVRegFloat(inst->VRegC_23x())));
@@ -2148,7 +2043,6 @@
}
ALWAYS_INLINE void ADD_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
shadow_frame.GetVRegDouble(inst->VRegB_23x()) +
shadow_frame.GetVRegDouble(inst->VRegC_23x()));
@@ -2156,7 +2050,6 @@
}
ALWAYS_INLINE void SUB_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
shadow_frame.GetVRegDouble(inst->VRegB_23x()) -
shadow_frame.GetVRegDouble(inst->VRegC_23x()));
@@ -2164,7 +2057,6 @@
}
ALWAYS_INLINE void MUL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
shadow_frame.GetVRegDouble(inst->VRegB_23x()) *
shadow_frame.GetVRegDouble(inst->VRegC_23x()));
@@ -2172,7 +2064,6 @@
}
ALWAYS_INLINE void DIV_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
shadow_frame.GetVRegDouble(inst->VRegB_23x()) /
shadow_frame.GetVRegDouble(inst->VRegC_23x()));
@@ -2180,7 +2071,6 @@
}
ALWAYS_INLINE void REM_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
fmod(shadow_frame.GetVRegDouble(inst->VRegB_23x()),
shadow_frame.GetVRegDouble(inst->VRegC_23x())));
@@ -2188,7 +2078,6 @@
}
ALWAYS_INLINE void ADD_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVReg(vregA, SafeAdd(shadow_frame.GetVReg(vregA),
shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
@@ -2196,7 +2085,6 @@
}
ALWAYS_INLINE void SUB_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVReg(vregA,
SafeSub(shadow_frame.GetVReg(vregA),
@@ -2205,7 +2093,6 @@
}
ALWAYS_INLINE void MUL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVReg(vregA,
SafeMul(shadow_frame.GetVReg(vregA),
@@ -2214,7 +2101,6 @@
}
ALWAYS_INLINE void DIV_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
bool success = DoIntDivide(shadow_frame, vregA, shadow_frame.GetVReg(vregA),
shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
@@ -2222,7 +2108,6 @@
}
ALWAYS_INLINE void REM_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
bool success = DoIntRemainder(shadow_frame, vregA, shadow_frame.GetVReg(vregA),
shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
@@ -2230,7 +2115,6 @@
}
ALWAYS_INLINE void SHL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVReg(vregA,
shadow_frame.GetVReg(vregA) <<
@@ -2239,7 +2123,6 @@
}
ALWAYS_INLINE void SHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVReg(vregA,
shadow_frame.GetVReg(vregA) >>
@@ -2248,7 +2131,6 @@
}
ALWAYS_INLINE void USHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVReg(vregA,
static_cast<uint32_t>(shadow_frame.GetVReg(vregA)) >>
@@ -2257,7 +2139,6 @@
}
ALWAYS_INLINE void AND_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVReg(vregA,
shadow_frame.GetVReg(vregA) &
@@ -2266,7 +2147,6 @@
}
ALWAYS_INLINE void OR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVReg(vregA,
shadow_frame.GetVReg(vregA) |
@@ -2275,7 +2155,6 @@
}
ALWAYS_INLINE void XOR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVReg(vregA,
shadow_frame.GetVReg(vregA) ^
@@ -2284,7 +2163,6 @@
}
ALWAYS_INLINE void ADD_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVRegLong(vregA,
SafeAdd(shadow_frame.GetVRegLong(vregA),
@@ -2293,7 +2171,6 @@
}
ALWAYS_INLINE void SUB_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVRegLong(vregA,
SafeSub(shadow_frame.GetVRegLong(vregA),
@@ -2302,7 +2179,6 @@
}
ALWAYS_INLINE void MUL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVRegLong(vregA,
SafeMul(shadow_frame.GetVRegLong(vregA),
@@ -2311,7 +2187,6 @@
}
ALWAYS_INLINE void DIV_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
DoLongDivide(shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
@@ -2319,7 +2194,6 @@
}
ALWAYS_INLINE void REM_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
DoLongRemainder(shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
@@ -2327,7 +2201,6 @@
}
ALWAYS_INLINE void AND_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVRegLong(vregA,
shadow_frame.GetVRegLong(vregA) &
@@ -2336,7 +2209,6 @@
}
ALWAYS_INLINE void OR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVRegLong(vregA,
shadow_frame.GetVRegLong(vregA) |
@@ -2345,7 +2217,6 @@
}
ALWAYS_INLINE void XOR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVRegLong(vregA,
shadow_frame.GetVRegLong(vregA) ^
@@ -2354,7 +2225,6 @@
}
ALWAYS_INLINE void SHL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVRegLong(vregA,
shadow_frame.GetVRegLong(vregA) <<
@@ -2363,7 +2233,6 @@
}
ALWAYS_INLINE void SHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVRegLong(vregA,
shadow_frame.GetVRegLong(vregA) >>
@@ -2372,7 +2241,6 @@
}
ALWAYS_INLINE void USHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVRegLong(vregA,
static_cast<uint64_t>(shadow_frame.GetVRegLong(vregA)) >>
@@ -2381,7 +2249,6 @@
}
ALWAYS_INLINE void ADD_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVRegFloat(vregA,
shadow_frame.GetVRegFloat(vregA) +
@@ -2390,7 +2257,6 @@
}
ALWAYS_INLINE void SUB_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVRegFloat(vregA,
shadow_frame.GetVRegFloat(vregA) -
@@ -2399,7 +2265,6 @@
}
ALWAYS_INLINE void MUL_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVRegFloat(vregA,
shadow_frame.GetVRegFloat(vregA) *
@@ -2408,7 +2273,6 @@
}
ALWAYS_INLINE void DIV_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVRegFloat(vregA,
shadow_frame.GetVRegFloat(vregA) /
@@ -2417,7 +2281,6 @@
}
ALWAYS_INLINE void REM_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVRegFloat(vregA,
fmodf(shadow_frame.GetVRegFloat(vregA),
@@ -2426,7 +2289,6 @@
}
ALWAYS_INLINE void ADD_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVRegDouble(vregA,
shadow_frame.GetVRegDouble(vregA) +
@@ -2435,7 +2297,6 @@
}
ALWAYS_INLINE void SUB_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVRegDouble(vregA,
shadow_frame.GetVRegDouble(vregA) -
@@ -2444,7 +2305,6 @@
}
ALWAYS_INLINE void MUL_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVRegDouble(vregA,
shadow_frame.GetVRegDouble(vregA) *
@@ -2453,7 +2313,6 @@
}
ALWAYS_INLINE void DIV_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVRegDouble(vregA,
shadow_frame.GetVRegDouble(vregA) /
@@ -2462,7 +2321,6 @@
}
ALWAYS_INLINE void REM_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
uint4_t vregA = inst->VRegA_12x(inst_data);
shadow_frame.SetVRegDouble(vregA,
fmod(shadow_frame.GetVRegDouble(vregA),
@@ -2471,7 +2329,6 @@
}
ALWAYS_INLINE void ADD_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
SafeAdd(shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
inst->VRegC_22s()));
@@ -2479,7 +2336,6 @@
}
ALWAYS_INLINE void RSUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
SafeSub(inst->VRegC_22s(),
shadow_frame.GetVReg(inst->VRegB_22s(inst_data))));
@@ -2487,7 +2343,6 @@
}
ALWAYS_INLINE void MUL_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
SafeMul(shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
inst->VRegC_22s()));
@@ -2495,7 +2350,6 @@
}
ALWAYS_INLINE void DIV_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoIntDivide(shadow_frame, inst->VRegA_22s(inst_data),
shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
inst->VRegC_22s());
@@ -2503,7 +2357,6 @@
}
ALWAYS_INLINE void REM_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoIntRemainder(shadow_frame, inst->VRegA_22s(inst_data),
shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
inst->VRegC_22s());
@@ -2511,7 +2364,6 @@
}
ALWAYS_INLINE void AND_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) &
inst->VRegC_22s());
@@ -2519,7 +2371,6 @@
}
ALWAYS_INLINE void OR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) |
inst->VRegC_22s());
@@ -2527,7 +2378,6 @@
}
ALWAYS_INLINE void XOR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) ^
inst->VRegC_22s());
@@ -2535,42 +2385,36 @@
}
ALWAYS_INLINE void ADD_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
SafeAdd(shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b()));
inst = inst->Next_2xx();
}
ALWAYS_INLINE void RSUB_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
SafeSub(inst->VRegC_22b(), shadow_frame.GetVReg(inst->VRegB_22b())));
inst = inst->Next_2xx();
}
ALWAYS_INLINE void MUL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
SafeMul(shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b()));
inst = inst->Next_2xx();
}
ALWAYS_INLINE void DIV_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoIntDivide(shadow_frame, inst->VRegA_22b(inst_data),
shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b());
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void REM_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
bool success = DoIntRemainder(shadow_frame, inst->VRegA_22b(inst_data),
shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b());
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
}
ALWAYS_INLINE void AND_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
shadow_frame.GetVReg(inst->VRegB_22b()) &
inst->VRegC_22b());
@@ -2578,7 +2422,6 @@
}
ALWAYS_INLINE void OR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
shadow_frame.GetVReg(inst->VRegB_22b()) |
inst->VRegC_22b());
@@ -2586,7 +2429,6 @@
}
ALWAYS_INLINE void XOR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
shadow_frame.GetVReg(inst->VRegB_22b()) ^
inst->VRegC_22b());
@@ -2594,7 +2436,6 @@
}
ALWAYS_INLINE void SHL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
shadow_frame.GetVReg(inst->VRegB_22b()) <<
(inst->VRegC_22b() & 0x1f));
@@ -2602,7 +2443,6 @@
}
ALWAYS_INLINE void SHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
shadow_frame.GetVReg(inst->VRegB_22b()) >>
(inst->VRegC_22b() & 0x1f));
@@ -2610,7 +2450,6 @@
}
ALWAYS_INLINE void USHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
- PREAMBLE();
shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
static_cast<uint32_t>(shadow_frame.GetVReg(inst->VRegB_22b())) >>
(inst->VRegC_22b() & 0x1f));
@@ -2712,20 +2551,11 @@
bool& exit_interpreter_loop;
};
-#undef HANDLE_BACKWARD_BRANCH
-#undef HANDLE_ASYNC_EXCEPTION
-#undef HOTNESS_UPDATE
#undef BRANCH_INSTRUMENTATION
-#undef PREAMBLE
-#undef PREAMBLE_SAVE
-#undef HANDLE_MONITOR_CHECKS
#undef POSSIBLY_HANDLE_PENDING_EXCEPTION
#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE
#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC
-#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_IMPL
#undef HANDLE_PENDING_EXCEPTION
-#undef HANDLE_PENDING_EXCEPTION_WITH_INSTRUMENTATION
-#undef CHECK_FORCE_RETURN
// TODO On ASAN builds this function gets a huge stack frame. Since normally we run in the mterp
// this shouldn't cause any problems for stack overflow detection. Remove this once b/117341496 is
@@ -2763,8 +2593,10 @@
bool exit_loop = false; \
InstructionHandler<do_access_check, transaction_active> handler( \
ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, exit_loop); \
- /* TODO: Call PREAMBLE here, instead of explicitly in each handler */ \
- handler.OPCODE_NAME(); \
+ constexpr bool is_move_result_object = (OPCODE == Instruction::MOVE_RESULT_OBJECT); \
+ if (handler.PreambleSave(is_move_result_object ? &ctx->result_register : nullptr)) { \
+ handler.OPCODE_NAME(); \
+ } \
/* TODO: Advance 'inst' here, instead of explicitly in each handler */ \
if (UNLIKELY(exit_loop)) { \
return; \
diff --git a/runtime/native_stack_dump.cc b/runtime/native_stack_dump.cc
index 10f5898..88adad0 100644
--- a/runtime/native_stack_dump.cc
+++ b/runtime/native_stack_dump.cc
@@ -373,7 +373,7 @@
}
os << std::endl;
if (try_addr2line && use_addr2line) {
- Addr2line(it->map.name, it->pc - it->map.start, os, prefix, &addr2line_state);
+ Addr2line(it->map.name, it->rel_pc, os, prefix, &addr2line_state);
}
}
diff --git a/runtime/oat.h b/runtime/oat.h
index 2a6d738..b07294a 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -34,7 +34,6 @@
// Last oat version changed reason: Remove interpreter alt tables.
static constexpr uint8_t kOatVersion[] = { '1', '6', '3', '\0' };
- static constexpr const char* kImageLocationKey = "image-location";
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
static constexpr const char* kDex2OatHostKey = "dex2oat-host";
static constexpr const char* kDebuggableKey = "debuggable";
diff --git a/test/1958-transform-try-jit/expected.txt b/test/1958-transform-try-jit/expected.txt
new file mode 100644
index 0000000..8cfaea2
--- /dev/null
+++ b/test/1958-transform-try-jit/expected.txt
@@ -0,0 +1,2 @@
+Before redefinition: hello
+After redefinition: Goodbye
diff --git a/test/1958-transform-try-jit/info.txt b/test/1958-transform-try-jit/info.txt
new file mode 100644
index 0000000..0bf5ee5
--- /dev/null
+++ b/test/1958-transform-try-jit/info.txt
@@ -0,0 +1,5 @@
+Tests that JVMTI transformation seems to work even when we try to get a method
+inlined by the jit.
+
+Note this test deliberately avoids any internal libart calls so it can be
+included in CTS.
diff --git a/test/1958-transform-try-jit/run b/test/1958-transform-try-jit/run
new file mode 100755
index 0000000..c6e62ae
--- /dev/null
+++ b/test/1958-transform-try-jit/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+./default-run "$@" --jvmti
diff --git a/test/1958-transform-try-jit/src/Main.java b/test/1958-transform-try-jit/src/Main.java
new file mode 100644
index 0000000..7f45c20
--- /dev/null
+++ b/test/1958-transform-try-jit/src/Main.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+ public static void main(String[] args) throws Exception {
+ art.Test1958.run();
+ }
+}
diff --git a/test/1958-transform-try-jit/src/art/Redefinition.java b/test/1958-transform-try-jit/src/art/Redefinition.java
new file mode 100644
index 0000000..56d2938
--- /dev/null
+++ b/test/1958-transform-try-jit/src/art/Redefinition.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package art;
+
+import java.util.ArrayList;
+// Common Redefinition functions. Placed here for use by CTS
+public class Redefinition {
+ public static final class CommonClassDefinition {
+ public final Class<?> target;
+ public final byte[] class_file_bytes;
+ public final byte[] dex_file_bytes;
+
+ public CommonClassDefinition(Class<?> target, byte[] class_file_bytes, byte[] dex_file_bytes) {
+ this.target = target;
+ this.class_file_bytes = class_file_bytes;
+ this.dex_file_bytes = dex_file_bytes;
+ }
+ }
+
+ // A set of possible test configurations. Test should set this if they need to.
+ // This must be kept in sync with the defines in ti-agent/common_helper.cc
+ public static enum Config {
+ COMMON_REDEFINE(0),
+ COMMON_RETRANSFORM(1),
+ COMMON_TRANSFORM(2);
+
+ private final int val;
+ private Config(int val) {
+ this.val = val;
+ }
+ }
+
+ public static void setTestConfiguration(Config type) {
+ nativeSetTestConfiguration(type.val);
+ }
+
+ private static native void nativeSetTestConfiguration(int type);
+
+ // Transforms the class
+ public static native void doCommonClassRedefinition(Class<?> target,
+ byte[] classfile,
+ byte[] dexfile);
+
+ public static void doMultiClassRedefinition(CommonClassDefinition... defs) {
+ ArrayList<Class<?>> classes = new ArrayList<>();
+ ArrayList<byte[]> class_files = new ArrayList<>();
+ ArrayList<byte[]> dex_files = new ArrayList<>();
+
+ for (CommonClassDefinition d : defs) {
+ classes.add(d.target);
+ class_files.add(d.class_file_bytes);
+ dex_files.add(d.dex_file_bytes);
+ }
+ doCommonMultiClassRedefinition(classes.toArray(new Class<?>[0]),
+ class_files.toArray(new byte[0][]),
+ dex_files.toArray(new byte[0][]));
+ }
+
+ public static void addMultiTransformationResults(CommonClassDefinition... defs) {
+ for (CommonClassDefinition d : defs) {
+ addCommonTransformationResult(d.target.getCanonicalName(),
+ d.class_file_bytes,
+ d.dex_file_bytes);
+ }
+ }
+
+ public static native void doCommonMultiClassRedefinition(Class<?>[] targets,
+ byte[][] classfiles,
+ byte[][] dexfiles);
+ public static native void doCommonClassRetransformation(Class<?>... target);
+ public static native void setPopRetransformations(boolean pop);
+ public static native void popTransformationFor(String name);
+ public static native void enableCommonRetransformation(boolean enable);
+ public static native void addCommonTransformationResult(String target_name,
+ byte[] class_bytes,
+ byte[] dex_bytes);
+}
diff --git a/test/1958-transform-try-jit/src/art/Test1958.java b/test/1958-transform-try-jit/src/art/Test1958.java
new file mode 100644
index 0000000..100daa1
--- /dev/null
+++ b/test/1958-transform-try-jit/src/art/Test1958.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package art;
+
+import java.lang.reflect.Method;
+import java.util.Base64;
+
+public class Test1958 {
+ static class Runner {
+ public static String doSayHi() {
+ return sayHiHelper(true);
+ }
+
+ public static String dontSayHi() {
+ return sayHiHelper(false);
+ }
+
+ // We are trying to get the definition of Transform.sayHi inlined into this function.
+ public static String sayHiHelper(boolean sayHi) {
+ if (sayHi) {
+ return Transform.sayHi();
+ } else {
+ return "NOPE!";
+ }
+ }
+ }
+
+ static class Transform {
+ public static String sayHi() {
+ // Use lower 'h' to make sure the string will have a different string id
+ // than the transformation (the transformation code is the same except
+ // the actual printed String, which was making the test inacurately passing
+ // in JIT mode when loading the string from the dex cache, as the string ids
+ // of the two different strings were the same).
+ // We know the string ids will be different because lexicographically:
+ // "Goodbye" < "LTransform;" < "hello".
+ return "hello";
+ }
+ }
+
+ /**
+ * base64 encoded class/dex file for
+ * static class Transform {
+ * public static String sayHi() {
+ * return "Goodbye";
+ * }
+ * }
+ */
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADUAFQoABAANCAAOBwAQBwATAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1i" +
+ "ZXJUYWJsZQEABXNheUhpAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAApTb3VyY2VGaWxlAQANVGVz" +
+ "dDE5NTguamF2YQwABQAGAQAHR29vZGJ5ZQcAFAEAFmFydC9UZXN0MTk1OCRUcmFuc2Zvcm0BAAlU" +
+ "cmFuc2Zvcm0BAAxJbm5lckNsYXNzZXMBABBqYXZhL2xhbmcvT2JqZWN0AQAMYXJ0L1Rlc3QxOTU4" +
+ "ACAAAwAEAAAAAAACAAAABQAGAAEABwAAAB0AAQABAAAABSq3AAGxAAAAAQAIAAAABgABAAAABgAJ" +
+ "AAkACgABAAcAAAAbAAEAAAAAAAMSArAAAAABAAgAAAAGAAEAAAAIAAIACwAAAAIADAASAAAACgAB" +
+ "AAMADwARAAg=");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQCRmEaLPLzpKe+CHcDM8YhIJCPWwcFR5yegAwAAcAAAAHhWNBIAAAAAAAAAAPQCAAAR" +
+ "AAAAcAAAAAcAAAC0AAAAAgAAANAAAAAAAAAAAAAAAAMAAADoAAAAAQAAAAABAACAAgAAIAEAAFgB" +
+ "AABgAQAAaQEAAGwBAACGAQAAlgEAALoBAADaAQAA7gEAAAICAAARAgAAHAIAAB8CAAAsAgAAMgIA" +
+ "ADkCAABAAgAAAwAAAAQAAAAFAAAABgAAAAcAAAAIAAAACwAAAAIAAAAFAAAAAAAAAAsAAAAGAAAA" +
+ "AAAAAAAAAQAAAAAAAAAAAA4AAAAEAAEAAAAAAAAAAAAAAAAABAAAAAAAAAAJAAAA5AIAAMYCAAAA" +
+ "AAAAAQAAAAAAAABUAQAAAwAAABoAAQARAAAAAQABAAEAAABQAQAABAAAAHAQAgAAAA4ABgAOAAgA" +
+ "DgAGPGluaXQ+AAdHb29kYnllAAFMABhMYXJ0L1Rlc3QxOTU4JFRyYW5zZm9ybTsADkxhcnQvVGVz" +
+ "dDE5NTg7ACJMZGFsdmlrL2Fubm90YXRpb24vRW5jbG9zaW5nQ2xhc3M7AB5MZGFsdmlrL2Fubm90" +
+ "YXRpb24vSW5uZXJDbGFzczsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7" +
+ "AA1UZXN0MTk1OC5qYXZhAAlUcmFuc2Zvcm0AAVYAC2FjY2Vzc0ZsYWdzAARuYW1lAAVzYXlIaQAF" +
+ "dmFsdWUAdX5+RDh7ImNvbXBpbGF0aW9uLW1vZGUiOiJkZWJ1ZyIsIm1pbi1hcGkiOjEsInNoYS0x" +
+ "IjoiNTFjYWNlMWFiZGQwOGIzMjBmMjVmYjgxMTZjMjQzMmIwMmYwOTI5NSIsInZlcnNpb24iOiIx" +
+ "LjQuNS1kZXYifQACAgEPGAECAwIMBAgNFwoAAAIAAICABLgCAQmgAgAAAAACAAAAtwIAAL0CAADY" +
+ "AgAAAAAAAAAAAAAAAAAADgAAAAAAAAABAAAAAAAAAAEAAAARAAAAcAAAAAIAAAAHAAAAtAAAAAMA" +
+ "AAACAAAA0AAAAAUAAAADAAAA6AAAAAYAAAABAAAAAAEAAAEgAAACAAAAIAEAAAMgAAACAAAAUAEA" +
+ "AAIgAAARAAAAWAEAAAQgAAACAAAAtwIAAAAgAAABAAAAxgIAAAMQAAACAAAA1AIAAAYgAAABAAAA" +
+ "5AIAAAAQAAABAAAA9AIAAA==");
+
+ public static void run() throws Exception {
+ Redefinition.setTestConfiguration(Redefinition.Config.COMMON_REDEFINE);
+ Method doSayHi = Runner.class.getDeclaredMethod("doSayHi");
+ Method dontSayHi = Runner.class.getDeclaredMethod("dontSayHi");
+ // Run the method enough times that the jit thinks it's interesting (default 10000).
+ for (int i = 0; i < 20000; i++) {
+ doSayHi.invoke(null);
+ dontSayHi.invoke(null);
+ }
+ // Sleep for 10 seconds to let the jit finish any work it's doing.
+ Thread.sleep(10 * 1000);
+ // Check what we get right now.
+ System.out.println("Before redefinition: " + doSayHi.invoke(null));
+ Redefinition.doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES);
+ System.out.println("After redefinition: " + doSayHi.invoke(null));
+ }
+}
diff --git a/tools/timeout_dumper/timeout_dumper.cc b/tools/timeout_dumper/timeout_dumper.cc
index cb3eaa5..30e194c 100644
--- a/tools/timeout_dumper/timeout_dumper.cc
+++ b/tools/timeout_dumper/timeout_dumper.cc
@@ -25,6 +25,7 @@
#include <csignal>
#include <cstdlib>
#include <cstring>
+#include <iostream>
#include <thread>
#include <memory>
#include <set>
@@ -246,10 +247,7 @@
break;
} else {
- char saved = *(new_line + 1);
- *(new_line + 1) = 0;
- os << tmp;
- *(new_line + 1) = saved;
+ os << std::string(tmp, new_line - tmp + 1);
tmp = new_line + 1;
prefix_written = false;
@@ -284,7 +282,7 @@
}
pipe->reset(); // Close early.
- const char* args[7] = {
+ const char* args[] = {
addr2line.c_str(),
"--functions",
"--inlines",
@@ -360,18 +358,54 @@
} // namespace ptrace
-bool WaitForSigStoppedOrError(pid_t pid) {
- int status;
- pid_t res = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
- if (res == -1) {
- PLOG(ERROR) << "Failed to waitpid for " << pid;
- return false;
+template <typename T>
+bool WaitLoop(uint32_t max_wait_micros, const T& handler) {
+ constexpr uint32_t kWaitMicros = 10;
+ const size_t kMaxLoopCount = max_wait_micros / kWaitMicros;
+
+ for (size_t loop_count = 1; loop_count <= kMaxLoopCount; ++loop_count) {
+ bool ret;
+ if (handler(&ret)) {
+ return ret;
+ }
+ usleep(kWaitMicros);
}
- if (!(WIFSTOPPED(status))) {
- LOG(ERROR) << "Did not get expected stopped signal for " << pid;
+ return false;
+}
+
+bool WaitForMainSigStop(const std::atomic<bool>& saw_wif_stopped_for_main) {
+ auto handler = [&](bool* res) {
+ if (saw_wif_stopped_for_main) {
+ *res = true;
+ return true;
+ }
return false;
- }
- return true;
+ };
+ constexpr uint32_t kMaxWaitMicros = 30 * 1000 * 1000; // 30s wait.
+ return WaitLoop(kMaxWaitMicros, handler);
+}
+
+bool WaitForSigStopped(pid_t pid, uint32_t max_wait_micros) {
+ auto handler = [&](bool* res) {
+ int status;
+ pid_t rc = TEMP_FAILURE_RETRY(waitpid(pid, &status, WNOHANG));
+ if (rc == -1) {
+ PLOG(ERROR) << "Failed to waitpid for " << pid;
+ *res = false;
+ return true;
+ }
+ if (rc == pid) {
+ if (!(WIFSTOPPED(status))) {
+ LOG(ERROR) << "Did not get expected stopped signal for " << pid;
+ *res = false;
+ } else {
+ *res = true;
+ }
+ return true;
+ }
+ return false;
+ };
+ return WaitLoop(max_wait_micros, handler);
}
#ifdef __LP64__
@@ -385,8 +419,12 @@
const std::string* addr2line_path,
const char* prefix,
BacktraceMap* map) {
- if (pid != tid && !WaitForSigStoppedOrError(tid)) {
- return;
+ // Use std::cerr to avoid the LOG prefix.
+ std::cerr << std::endl << "=== pid: " << pid << " tid: " << tid << " ===" << std::endl;
+
+ constexpr uint32_t kMaxWaitMicros = 1000 * 1000; // 1s.
+ if (pid != tid && !WaitForSigStopped(tid, kMaxWaitMicros)) {
+ LOG(ERROR) << "Failed to wait for sigstop on " << tid;
}
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid, map));
@@ -440,40 +478,22 @@
}
oss << ")";
}
- LOG(ERROR) << oss.str();
+ std::cerr << oss.str() << std::endl;
if (try_addr2line && addr2line_path != nullptr) {
addr2line::Addr2line(*addr2line_path,
it->map.name,
- it->pc - it->map.start,
- LOG_STREAM(ERROR),
+ it->rel_pc,
+ std::cerr,
prefix,
&addr2line_state);
}
}
if (addr2line_state != nullptr) {
- addr2line::Drain(0, prefix, &addr2line_state, LOG_STREAM(ERROR));
+ addr2line::Drain(0, prefix, &addr2line_state, std::cerr);
}
}
-bool WaitForMainSigStop(const std::atomic<bool>& saw_wif_stopped_for_main) {
- constexpr uint32_t kWaitMicros = 10;
- constexpr size_t kMaxLoopCount = 10 * 1000 * 1000 / kWaitMicros; // 10s wait.
-
- for (size_t loop_count = 0; !saw_wif_stopped_for_main; ++loop_count) {
- if (loop_count > kMaxLoopCount) {
- LOG(ERROR) << "Waited too long for main pid to stop";
- return false;
- }
-
- timespec tm;
- tm.tv_sec = 0;
- tm.tv_nsec = kWaitMicros * 1000;
- nanosleep(&tm, nullptr);
- }
- return true;
-}
-
void DumpProcess(pid_t forked_pid, const std::atomic<bool>& saw_wif_stopped_for_main) {
CHECK_EQ(0, ::ptrace(PTRACE_ATTACH, forked_pid, 0, 0));
std::set<pid_t> tids = ptrace::PtraceSiblings(forked_pid);
@@ -490,7 +510,7 @@
LOG(ERROR) << (use_addr2line ? "U" : "Not u") << "sing addr2line";
if (!WaitForMainSigStop(saw_wif_stopped_for_main)) {
- return;
+ LOG(ERROR) << "Did not receive SIGSTOP for pid " << forked_pid;
}
std::unique_ptr<BacktraceMap> backtrace_map(BacktraceMap::Create(forked_pid));
@@ -500,7 +520,6 @@
}
for (pid_t tid : tids) {
- LOG(ERROR) << "pid: " << forked_pid << " tid: " << tid;
DumpThread(forked_pid,
tid,
use_addr2line ? addr2line_path.get() : nullptr,