Move dex exception helpers to their own file and use dex accessor
Also change the input argument to be a code item accessor
instead of a code item pointer. This removes the dependency on
the code item layout.
Bug: 63756964
Test: test-art-host
Change-Id: If75a168d0b5a77d08fa3c6ba38d00705158911db
diff --git a/compiler/exception_test.cc b/compiler/exception_test.cc
index 4dbef0d..59d20f8 100644
--- a/compiler/exception_test.cc
+++ b/compiler/exception_test.cc
@@ -24,6 +24,7 @@
#include "common_runtime_test.h"
#include "dex_file-inl.h"
#include "dex_file.h"
+#include "dex_file_exception_helpers.h"
#include "gtest/gtest.h"
#include "handle_scope-inl.h"
#include "leb128.h"
@@ -129,20 +130,18 @@
TEST_F(ExceptionTest, FindCatchHandler) {
ScopedObjectAccess soa(Thread::Current());
- const DexFile::CodeItem* code_item = dex_->GetCodeItem(method_f_->GetCodeItemOffset());
- CodeItemDataAccessor accessor(dex_, code_item);
+ CodeItemDataAccessor accessor(dex_, dex_->GetCodeItem(method_f_->GetCodeItemOffset()));
- ASSERT_TRUE(code_item != nullptr);
+ ASSERT_TRUE(accessor.HasCodeItem());
ASSERT_EQ(2u, accessor.TriesSize());
ASSERT_NE(0u, accessor.InsnsSizeInCodeUnits());
- const DexFile::TryItem *t0, *t1;
- t0 = dex_->GetTryItems(*code_item, 0);
- t1 = dex_->GetTryItems(*code_item, 1);
- EXPECT_LE(t0->start_addr_, t1->start_addr_);
+ const DexFile::TryItem& t0 = accessor.TryItems().begin()[0];
+ const DexFile::TryItem& t1 = accessor.TryItems().begin()[1];
+ EXPECT_LE(t0.start_addr_, t1.start_addr_);
{
- CatchHandlerIterator iter(*code_item, 4 /* Dex PC in the first try block */);
+ CatchHandlerIterator iter(accessor, 4 /* Dex PC in the first try block */);
EXPECT_STREQ("Ljava/io/IOException;", dex_->StringByTypeIdx(iter.GetHandlerTypeIndex()));
ASSERT_TRUE(iter.HasNext());
iter.Next();
@@ -152,14 +151,14 @@
EXPECT_FALSE(iter.HasNext());
}
{
- CatchHandlerIterator iter(*code_item, 8 /* Dex PC in the second try block */);
+ CatchHandlerIterator iter(accessor, 8 /* Dex PC in the second try block */);
EXPECT_STREQ("Ljava/io/IOException;", dex_->StringByTypeIdx(iter.GetHandlerTypeIndex()));
ASSERT_TRUE(iter.HasNext());
iter.Next();
EXPECT_FALSE(iter.HasNext());
}
{
- CatchHandlerIterator iter(*code_item, 11 /* Dex PC not in any try block */);
+ CatchHandlerIterator iter(accessor, 11 /* Dex PC not in any try block */);
EXPECT_FALSE(iter.HasNext());
}
}
diff --git a/compiler/optimizing/block_builder.cc b/compiler/optimizing/block_builder.cc
index c505efa..0c92600 100644
--- a/compiler/optimizing/block_builder.cc
+++ b/compiler/optimizing/block_builder.cc
@@ -19,6 +19,7 @@
#include "base/logging.h" // FOR VLOG.
#include "bytecode_utils.h"
#include "code_item_accessors-inl.h"
+#include "dex_file_exception_helpers.h"
#include "quicken_info.h"
namespace art {
diff --git a/dexdump/dexdump.cc b/dexdump/dexdump.cc
index 730d4b9..ba2a922 100644
--- a/dexdump/dexdump.cc
+++ b/dexdump/dexdump.cc
@@ -48,6 +48,7 @@
#include "dex_file-inl.h"
#include "dex_file_loader.h"
#include "dex_file_types.h"
+#include "dex_file_exception_helpers.h"
#include "dex_instruction-inl.h"
#include "dexdump_cfg.h"
@@ -735,7 +736,8 @@
* Dumps the catches table associated with the code.
*/
static void dumpCatches(const DexFile* pDexFile, const DexFile::CodeItem* pCode) {
- const u4 triesSize = CodeItemDataAccessor(pDexFile, pCode).TriesSize();
+ CodeItemDataAccessor accessor(pDexFile, pCode);
+ const u4 triesSize = accessor.TriesSize();
// No catch table.
if (triesSize == 0) {
@@ -745,12 +747,11 @@
// Dump all table entries.
fprintf(gOutFile, " catches : %d\n", triesSize);
- for (u4 i = 0; i < triesSize; i++) {
- const DexFile::TryItem* pTry = pDexFile->GetTryItems(*pCode, i);
- const u4 start = pTry->start_addr_;
- const u4 end = start + pTry->insn_count_;
+ for (const DexFile::TryItem& try_item : accessor.TryItems()) {
+ const u4 start = try_item.start_addr_;
+ const u4 end = start + try_item.insn_count_;
fprintf(gOutFile, " 0x%04x - 0x%04x\n", start, end);
- for (CatchHandlerIterator it(*pCode, *pTry); it.HasNext(); it.Next()) {
+ for (CatchHandlerIterator it(accessor, try_item); it.HasNext(); it.Next()) {
const dex::TypeIndex tidx = it.GetHandlerTypeIndex();
const char* descriptor = (!tidx.IsValid()) ? "<any>" : pDexFile->StringByTypeIdx(tidx);
fprintf(gOutFile, " %s -> 0x%04x\n", descriptor, it.GetHandlerAddress());
diff --git a/dexdump/dexdump_cfg.cc b/dexdump/dexdump_cfg.cc
index dd57a11..7e9f113 100644
--- a/dexdump/dexdump_cfg.cc
+++ b/dexdump/dexdump_cfg.cc
@@ -27,6 +27,7 @@
#include "code_item_accessors-no_art-inl.h"
#include "dex_file-inl.h"
+#include "dex_file_exception_helpers.h"
#include "dex_instruction-inl.h"
namespace art {
@@ -38,7 +39,7 @@
os << "digraph {\n";
os << " # /* " << dex_file->PrettyMethod(dex_method_idx, true) << " */\n";
- CodeItemInstructionAccessor accessor(dex_file, code_item);
+ CodeItemDataAccessor accessor(dex_file, code_item);
std::set<uint32_t> dex_pc_is_branch_target;
{
@@ -195,7 +196,7 @@
}
// Look at the exceptions of the first entry.
- CatchHandlerIterator catch_it(*code_item, dex_pc);
+ CatchHandlerIterator catch_it(accessor, dex_pc);
for (; catch_it.HasNext(); catch_it.Next()) {
exception_targets.insert(catch_it.GetHandlerAddress());
}
@@ -254,7 +255,7 @@
// Exception edges. If this is not the first instruction in the block
if (block_start_dex_pc != dex_pc) {
std::set<uint32_t> current_handler_pcs;
- CatchHandlerIterator catch_it(*code_item, dex_pc);
+ CatchHandlerIterator catch_it(accessor, dex_pc);
for (; catch_it.HasNext(); catch_it.Next()) {
current_handler_pcs.insert(catch_it.GetHandlerAddress());
}
@@ -295,7 +296,7 @@
const Instruction* inst = &accessor.InstructionAt(dex_pc);
uint32_t this_node_id = dex_pc_to_incl_id.find(dex_pc)->second;
while (true) {
- CatchHandlerIterator catch_it(*code_item, dex_pc);
+ CatchHandlerIterator catch_it(accessor, dex_pc);
if (catch_it.HasNext()) {
std::set<uint32_t> handled_targets;
for (; catch_it.HasNext(); catch_it.Next()) {
diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc
index a163bd9..157d4ef 100644
--- a/dexlayout/dex_ir.cc
+++ b/dexlayout/dex_ir.cc
@@ -23,6 +23,7 @@
#include "dex_ir.h"
#include "code_item_accessors-inl.h"
+#include "dex_file_exception_helpers.h"
#include "dex_instruction-inl.h"
#include "dex_ir_builder.h"
@@ -610,7 +611,7 @@
if (handlers == nullptr) {
bool catch_all = false;
TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
- for (CatchHandlerIterator it(disk_code_item, disk_try_item); it.HasNext(); it.Next()) {
+ for (CatchHandlerIterator it(accessor, disk_try_item); it.HasNext(); it.Next()) {
const dex::TypeIndex type_index = it.GetHandlerTypeIndex();
const TypeId* type_id = GetTypeIdOrNullPtr(type_index.index_);
catch_all |= type_id == nullptr;
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 1e5fe16..8fe901d 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -58,8 +58,9 @@
"compiler_filter.cc",
"debugger.cc",
"dex_file.cc",
- "dex_file_loader.cc",
"dex_file_annotations.cc",
+ "dex_file_exception_helpers.cc",
+ "dex_file_loader.cc",
"dex_file_layout.cc",
"dex_file_tracking_registrar.cc",
"dex_file_verifier.cc",
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index 7ddaa7e..d6e4ce5 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -26,6 +26,7 @@
#include "class_linker-inl.h"
#include "debugger.h"
#include "dex_file-inl.h"
+#include "dex_file_exception_helpers.h"
#include "dex_instruction.h"
#include "entrypoints/runtime_asm_entrypoints.h"
#include "gc/accounting/card_table-inl.h"
@@ -263,7 +264,6 @@
uint32_t ArtMethod::FindCatchBlock(Handle<mirror::Class> exception_type,
uint32_t dex_pc, bool* has_no_move_exception) {
- const DexFile::CodeItem* code_item = GetCodeItem();
// Set aside the exception while we resolve its type.
Thread* self = Thread::Current();
StackHandleScope<1> hs(self);
@@ -272,7 +272,8 @@
// Default to handler not found.
uint32_t found_dex_pc = dex::kDexNoIndex;
// Iterate over the catch handlers associated with dex_pc.
- for (CatchHandlerIterator it(*code_item, dex_pc); it.HasNext(); it.Next()) {
+ CodeItemDataAccessor accessor(this);
+ for (CatchHandlerIterator it(accessor, dex_pc); it.HasNext(); it.Next()) {
dex::TypeIndex iter_type_idx = it.GetHandlerTypeIndex();
// Catch all case
if (!iter_type_idx.IsValid()) {
@@ -297,7 +298,7 @@
}
}
if (found_dex_pc != dex::kDexNoIndex) {
- const Instruction& first_catch_instr = DexInstructions().InstructionAt(found_dex_pc);
+ const Instruction& first_catch_instr = accessor.InstructionAt(found_dex_pc);
*has_no_move_exception = (first_catch_instr.Opcode() != Instruction::MOVE_EXCEPTION);
}
// Put the exception back.
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 24fcce4..192517f 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -51,6 +51,7 @@
#include "compiler_callbacks.h"
#include "debugger.h"
#include "dex_file-inl.h"
+#include "dex_file_exception_helpers.h"
#include "dex_file_loader.h"
#include "entrypoints/entrypoint_utils.h"
#include "entrypoints/runtime_asm_entrypoints.h"
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index 4aed402..d136dc3 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -802,85 +802,6 @@
ptr_ += width;
}
-CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) {
- handler_.address_ = -1;
- int32_t offset = -1;
-
- // Short-circuit the overwhelmingly common cases.
- switch (code_item.tries_size_) {
- case 0:
- break;
- case 1: {
- const DexFile::TryItem* tries = DexFile::GetTryItems(code_item, 0);
- uint32_t start = tries->start_addr_;
- if (address >= start) {
- uint32_t end = start + tries->insn_count_;
- if (address < end) {
- offset = tries->handler_off_;
- }
- }
- break;
- }
- default:
- offset = DexFile::FindCatchHandlerOffset(code_item, address);
- }
- Init(code_item, offset);
-}
-
-CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item,
- const DexFile::TryItem& try_item) {
- handler_.address_ = -1;
- Init(code_item, try_item.handler_off_);
-}
-
-void CatchHandlerIterator::Init(const DexFile::CodeItem& code_item,
- int32_t offset) {
- if (offset >= 0) {
- Init(DexFile::GetCatchHandlerData(code_item, offset));
- } else {
- // Not found, initialize as empty
- current_data_ = nullptr;
- remaining_count_ = -1;
- catch_all_ = false;
- DCHECK(!HasNext());
- }
-}
-
-void CatchHandlerIterator::Init(const uint8_t* handler_data) {
- current_data_ = handler_data;
- remaining_count_ = DecodeSignedLeb128(¤t_data_);
-
- // If remaining_count_ is non-positive, then it is the negative of
- // the number of catch types, and the catches are followed by a
- // catch-all handler.
- if (remaining_count_ <= 0) {
- catch_all_ = true;
- remaining_count_ = -remaining_count_;
- } else {
- catch_all_ = false;
- }
- Next();
-}
-
-void CatchHandlerIterator::Next() {
- if (remaining_count_ > 0) {
- handler_.type_idx_ = dex::TypeIndex(DecodeUnsignedLeb128(¤t_data_));
- handler_.address_ = DecodeUnsignedLeb128(¤t_data_);
- remaining_count_--;
- return;
- }
-
- if (catch_all_) {
- handler_.type_idx_ = dex::TypeIndex(DexFile::kDexNoIndex16);
- handler_.address_ = DecodeUnsignedLeb128(¤t_data_);
- catch_all_ = false;
- return;
- }
-
- // no more handler
- remaining_count_ = -1;
-}
-
namespace dex {
std::ostream& operator<<(std::ostream& os, const StringIndex& index) {
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index f3a88f7..3ca9908 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -342,7 +342,6 @@
private:
ART_FRIEND_TEST(CodeItemAccessorsTest, TestDexInstructionsAccessor);
- friend class CatchHandlerIterator;
friend class CodeItemDataAccessor;
friend class CodeItemDebugInfoAccessor;
friend class CodeItemInstructionAccessor;
@@ -1466,47 +1465,6 @@
};
std::ostream& operator<<(std::ostream& os, const CallSiteArrayValueIterator::ValueType& code);
-class CatchHandlerIterator {
- public:
- CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address);
-
- CatchHandlerIterator(const DexFile::CodeItem& code_item,
- const DexFile::TryItem& try_item);
-
- explicit CatchHandlerIterator(const uint8_t* handler_data) {
- Init(handler_data);
- }
-
- dex::TypeIndex GetHandlerTypeIndex() const {
- return handler_.type_idx_;
- }
- uint32_t GetHandlerAddress() const {
- return handler_.address_;
- }
- void Next();
- bool HasNext() const {
- return remaining_count_ != -1 || catch_all_;
- }
- // End of this set of catch blocks, convenience method to locate next set of catch blocks
- const uint8_t* EndDataPointer() const {
- CHECK(!HasNext());
- return current_data_;
- }
-
- private:
- void Init(const DexFile::CodeItem& code_item, int32_t offset);
- void Init(const uint8_t* handler_data);
-
- struct CatchHandlerItem {
- dex::TypeIndex type_idx_; // type index of the caught exception type
- uint32_t address_; // handler address
- } handler_;
- const uint8_t* current_data_; // the current handler in dex file.
- int32_t remaining_count_; // number of handlers not read.
- bool catch_all_; // is there a handler that will catch all exceptions in case
- // that all typed handler does not match.
-};
-
} // namespace art
#endif // ART_RUNTIME_DEX_FILE_H_
diff --git a/runtime/dex_file_exception_helpers.cc b/runtime/dex_file_exception_helpers.cc
new file mode 100644
index 0000000..ad56eb0
--- /dev/null
+++ b/runtime/dex_file_exception_helpers.cc
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+#include "dex_file_exception_helpers.h"
+
+#include "code_item_accessors-no_art-inl.h"
+
+namespace art {
+
+CatchHandlerIterator::CatchHandlerIterator(const CodeItemDataAccessor& accessor, uint32_t address) {
+ handler_.address_ = -1;
+ int32_t offset = -1;
+
+ // Short-circuit the overwhelmingly common cases.
+ switch (accessor.TriesSize()) {
+ case 0:
+ break;
+ case 1: {
+ const DexFile::TryItem* tries = accessor.TryItems().begin();
+ uint32_t start = tries->start_addr_;
+ if (address >= start) {
+ uint32_t end = start + tries->insn_count_;
+ if (address < end) {
+ offset = tries->handler_off_;
+ }
+ }
+ break;
+ }
+ default: {
+ const DexFile::TryItem* try_item = accessor.FindTryItem(address);
+ offset = try_item != nullptr ? try_item->handler_off_ : -1;
+ break;
+ }
+ }
+ Init(accessor, offset);
+}
+
+CatchHandlerIterator::CatchHandlerIterator(const CodeItemDataAccessor& accessor,
+ const DexFile::TryItem& try_item) {
+ handler_.address_ = -1;
+ Init(accessor, try_item.handler_off_);
+}
+
+void CatchHandlerIterator::Init(const CodeItemDataAccessor& accessor, int32_t offset) {
+ if (offset >= 0) {
+ Init(accessor.GetCatchHandlerData(offset));
+ } else {
+ // Not found, initialize as empty
+ current_data_ = nullptr;
+ remaining_count_ = -1;
+ catch_all_ = false;
+ DCHECK(!HasNext());
+ }
+}
+
+void CatchHandlerIterator::Init(const uint8_t* handler_data) {
+ current_data_ = handler_data;
+ remaining_count_ = DecodeSignedLeb128(¤t_data_);
+
+ // If remaining_count_ is non-positive, then it is the negative of
+ // the number of catch types, and the catches are followed by a
+ // catch-all handler.
+ if (remaining_count_ <= 0) {
+ catch_all_ = true;
+ remaining_count_ = -remaining_count_;
+ } else {
+ catch_all_ = false;
+ }
+ Next();
+}
+
+void CatchHandlerIterator::Next() {
+ if (remaining_count_ > 0) {
+ handler_.type_idx_ = dex::TypeIndex(DecodeUnsignedLeb128(¤t_data_));
+ handler_.address_ = DecodeUnsignedLeb128(¤t_data_);
+ remaining_count_--;
+ return;
+ }
+
+ if (catch_all_) {
+ handler_.type_idx_ = dex::TypeIndex(DexFile::kDexNoIndex16);
+ handler_.address_ = DecodeUnsignedLeb128(¤t_data_);
+ catch_all_ = false;
+ return;
+ }
+
+ // no more handler
+ remaining_count_ = -1;
+}
+
+} // namespace art
diff --git a/runtime/dex_file_exception_helpers.h b/runtime/dex_file_exception_helpers.h
new file mode 100644
index 0000000..739ed1f
--- /dev/null
+++ b/runtime/dex_file_exception_helpers.h
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_RUNTIME_DEX_FILE_EXCEPTION_HELPERS_H_
+#define ART_RUNTIME_DEX_FILE_EXCEPTION_HELPERS_H_
+
+#include "dex_file.h"
+
+namespace art {
+
+class CodeItemDataAccessor;
+
+class CatchHandlerIterator {
+ public:
+ CatchHandlerIterator(const CodeItemDataAccessor& accessor, uint32_t address);
+
+ CatchHandlerIterator(const CodeItemDataAccessor& accessor, const DexFile::TryItem& try_item);
+
+ explicit CatchHandlerIterator(const uint8_t* handler_data) {
+ Init(handler_data);
+ }
+
+ dex::TypeIndex GetHandlerTypeIndex() const {
+ return handler_.type_idx_;
+ }
+ uint32_t GetHandlerAddress() const {
+ return handler_.address_;
+ }
+ void Next();
+ bool HasNext() const {
+ return remaining_count_ != -1 || catch_all_;
+ }
+ // End of this set of catch blocks, convenience method to locate next set of catch blocks
+ const uint8_t* EndDataPointer() const {
+ CHECK(!HasNext());
+ return current_data_;
+ }
+
+ private:
+ void Init(const CodeItemDataAccessor& accessor, int32_t offset);
+ void Init(const uint8_t* handler_data);
+
+ struct CatchHandlerItem {
+ dex::TypeIndex type_idx_; // type index of the caught exception type
+ uint32_t address_; // handler address
+ } handler_;
+ const uint8_t* current_data_; // the current handler in dex file.
+ int32_t remaining_count_; // number of handlers not read.
+ bool catch_all_; // is there a handler that will catch all exceptions in case
+ // that all typed handler does not match.
+};
+
+} // namespace art
+
+#endif // ART_RUNTIME_DEX_FILE_EXCEPTION_HELPERS_H_
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index be6915f..63f21f8 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -32,6 +32,7 @@
#include "class_linker.h"
#include "compiler_callbacks.h"
#include "dex_file-inl.h"
+#include "dex_file_exception_helpers.h"
#include "dex_instruction-inl.h"
#include "dex_instruction_utils.h"
#include "experimental_flags.h"
@@ -3630,7 +3631,7 @@
bool has_catch_all_handler = false;
const DexFile::TryItem* try_item = code_item_accessor_.FindTryItem(work_insn_idx_);
CHECK(try_item != nullptr);
- CatchHandlerIterator iterator(code_item_accessor_.GetCatchHandlerData(try_item->handler_off_));
+ CatchHandlerIterator iterator(code_item_accessor_, *try_item);
// Need the linker to try and resolve the handled class to check if it's Throwable.
ClassLinker* linker = Runtime::Current()->GetClassLinker();