Refactor DecodeDebugLocalInfo
Refactor the function to use a visitor instead of callback.
Test: test-art-ghost
Bug: 112311591
Bug: 77709234
Change-Id: I55385994952373b3fec4f9122400cf3c9d43da3b
diff --git a/compiler/debug/elf_debug_info_writer.h b/compiler/debug/elf_debug_info_writer.h
index 233f61c..fe05992 100644
--- a/compiler/debug/elf_debug_info_writer.h
+++ b/compiler/debug/elf_debug_info_writer.h
@@ -41,12 +41,6 @@
namespace art {
namespace debug {
-typedef std::vector<DexFile::LocalInfo> LocalInfos;
-
-static void LocalInfoCallback(void* ctx, const DexFile::LocalInfo& entry) {
- static_cast<LocalInfos*>(ctx)->push_back(entry);
-}
-
static std::vector<const char*> GetParamNames(const MethodDebugInfo* mi) {
std::vector<const char*> names;
DCHECK(mi->dex_file != nullptr);
@@ -251,11 +245,12 @@
}
// Write local variables.
- LocalInfos local_infos;
+ std::vector<DexFile::LocalInfo> local_infos;
if (accessor.DecodeDebugLocalInfo(is_static,
mi->dex_method_index,
- LocalInfoCallback,
- &local_infos)) {
+ [&](const DexFile::LocalInfo& entry) {
+ local_infos.push_back(entry);
+ })) {
for (const DexFile::LocalInfo& var : local_infos) {
if (var.reg_ < accessor.RegistersSize() - accessor.InsSize()) {
info_.StartTag(DW_TAG_variable);
diff --git a/dexdump/dexdump.cc b/dexdump/dexdump.cc
index 31bc6e3..95d88be 100644
--- a/dexdump/dexdump.cc
+++ b/dexdump/dexdump.cc
@@ -751,16 +751,6 @@
}
/*
- * Callback for dumping locals table entry.
- */
-static void dumpLocalsCb(void* /*context*/, const DexFile::LocalInfo& entry) {
- const char* signature = entry.signature_ != nullptr ? entry.signature_ : "";
- fprintf(gOutFile, " 0x%04x - 0x%04x reg=%d %s %s %s\n",
- entry.start_address_, entry.end_address_, entry.reg_,
- entry.name_, entry.descriptor_, signature);
-}
-
-/*
* Helper for dumpInstruction(), which builds the string
* representation for the index in the given instruction.
* Returns a pointer to a buffer of sufficient size.
@@ -1198,7 +1188,19 @@
return false;
});
fprintf(gOutFile, " locals : \n");
- accessor.DecodeDebugLocalInfo(is_static, idx, dumpLocalsCb, nullptr);
+ accessor.DecodeDebugLocalInfo(is_static,
+ idx,
+ [&](const DexFile::LocalInfo& entry) {
+ const char* signature = entry.signature_ != nullptr ? entry.signature_ : "";
+ fprintf(gOutFile,
+ " 0x%04x - 0x%04x reg=%d %s %s %s\n",
+ entry.start_address_,
+ entry.end_address_,
+ entry.reg_,
+ entry.name_,
+ entry.descriptor_,
+ signature);
+ });
}
/*
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index 148c0c7..b539f5d 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -1037,17 +1037,6 @@
}
/*
- * Callback for dumping locals table entry.
- */
-static void DumpLocalsCb(void* context, const DexFile::LocalInfo& entry) {
- const char* signature = entry.signature_ != nullptr ? entry.signature_ : "";
- FILE* out_file = reinterpret_cast<FILE*>(context);
- fprintf(out_file, " 0x%04x - 0x%04x reg=%d %s %s %s\n",
- entry.start_address_, entry.end_address_, entry.reg_,
- entry.name_, entry.descriptor_, signature);
-}
-
-/*
* Lookup functions.
*/
static const char* StringDataByIdx(uint32_t idx, dex_ir::Header* header) {
@@ -1140,8 +1129,18 @@
StringDataByTypeIdx(dchecked_integral_cast<uint16_t>(idx),
this->header_);
},
- DumpLocalsCb,
- out_file_);
+ [&](const DexFile::LocalInfo& entry) {
+ const char* signature =
+ entry.signature_ != nullptr ? entry.signature_ : "";
+ fprintf(out_file_,
+ " 0x%04x - 0x%04x reg=%d %s %s %s\n",
+ entry.start_address_,
+ entry.end_address_,
+ entry.reg_,
+ entry.name_,
+ entry.descriptor_,
+ signature);
+ });
}
}
diff --git a/libdexfile/dex/code_item_accessors-inl.h b/libdexfile/dex/code_item_accessors-inl.h
index c7e876e..bbf2224 100644
--- a/libdexfile/dex/code_item_accessors-inl.h
+++ b/libdexfile/dex/code_item_accessors-inl.h
@@ -184,19 +184,18 @@
CodeItemDataAccessor::Init(code_item);
}
-template<typename NewLocalCallback>
-inline bool CodeItemDebugInfoAccessor::DecodeDebugLocalInfo(bool is_static,
- uint32_t method_idx,
- NewLocalCallback new_local,
- void* context) const {
+template<typename NewLocalVisitor>
+inline bool CodeItemDebugInfoAccessor::DecodeDebugLocalInfo(
+ bool is_static,
+ uint32_t method_idx,
+ const NewLocalVisitor& new_local) const {
return dex_file_->DecodeDebugLocalInfo(RegistersSize(),
InsSize(),
InsnsSizeInCodeUnits(),
DebugInfoOffset(),
is_static,
method_idx,
- new_local,
- context);
+ new_local);
}
template <typename Visitor>
diff --git a/libdexfile/dex/code_item_accessors.h b/libdexfile/dex/code_item_accessors.h
index c2aa23c..c307c9f 100644
--- a/libdexfile/dex/code_item_accessors.h
+++ b/libdexfile/dex/code_item_accessors.h
@@ -151,11 +151,10 @@
return debug_info_offset_;
}
- template<typename NewLocalCallback>
+ template<typename NewLocalVisitor>
bool DecodeDebugLocalInfo(bool is_static,
uint32_t method_idx,
- NewLocalCallback new_local,
- void* context) const;
+ const NewLocalVisitor& new_local) const;
// Visit each parameter in the debug information. Returns the line number.
// The argument of the Visitor is dex::StringIndex.
diff --git a/libdexfile/dex/dex_file-inl.h b/libdexfile/dex/dex_file-inl.h
index eca9ee9..eae7efc 100644
--- a/libdexfile/dex/dex_file-inl.h
+++ b/libdexfile/dex/dex_file-inl.h
@@ -215,10 +215,9 @@
uint16_t registers_size,
uint16_t ins_size,
uint16_t insns_size_in_code_units,
- IndexToStringData index_to_string_data,
- TypeIndexToStringData type_index_to_string_data,
- NewLocalCallback new_local_callback,
- void* context) {
+ const IndexToStringData& index_to_string_data,
+ const TypeIndexToStringData& type_index_to_string_data,
+ const NewLocalCallback& new_local_callback) {
if (stream == nullptr) {
return false;
}
@@ -278,7 +277,7 @@
for (uint16_t reg = 0; reg < registers_size; reg++) {
if (local_in_reg[reg].is_live_) {
local_in_reg[reg].end_address_ = insns_size_in_code_units;
- new_local_callback(context, local_in_reg[reg]);
+ new_local_callback(local_in_reg[reg]);
}
}
return true;
@@ -307,7 +306,7 @@
// Emit what was previously there, if anything
if (local_in_reg[reg].is_live_) {
local_in_reg[reg].end_address_ = address;
- new_local_callback(context, local_in_reg[reg]);
+ new_local_callback(local_in_reg[reg]);
}
local_in_reg[reg].name_ = index_to_string_data(name_idx);
@@ -329,7 +328,7 @@
// closed register is sloppy, but harmless if no further action is taken.
if (local_in_reg[reg].is_live_) {
local_in_reg[reg].end_address_ = address;
- new_local_callback(context, local_in_reg[reg]);
+ new_local_callback(local_in_reg[reg]);
local_in_reg[reg].is_live_ = false;
}
break;
@@ -369,8 +368,7 @@
uint32_t debug_info_offset,
bool is_static,
uint32_t method_idx,
- NewLocalCallback new_local_callback,
- void* context) const {
+ const NewLocalCallback& new_local_callback) const {
const uint8_t* const stream = GetDebugInfoStream(debug_info_offset);
if (stream == nullptr) {
return false;
@@ -396,8 +394,7 @@
return StringByTypeIdx(dex::TypeIndex(
dchecked_integral_cast<uint16_t>(idx)));
},
- new_local_callback,
- context);
+ new_local_callback);
}
template<typename DexDebugNewPosition, typename IndexToStringData>
diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h
index 3e4a481..30d8b6d 100644
--- a/libdexfile/dex/dex_file.h
+++ b/libdexfile/dex/dex_file.h
@@ -874,10 +874,9 @@
uint16_t registers_size,
uint16_t ins_size,
uint16_t insns_size_in_code_units,
- IndexToStringData index_to_string_data,
- TypeIndexToStringData type_index_to_string_data,
- NewLocalCallback new_local,
- void* context);
+ const IndexToStringData& index_to_string_data,
+ const TypeIndexToStringData& type_index_to_string_data,
+ const NewLocalCallback& new_local) NO_THREAD_SAFETY_ANALYSIS;
template<typename NewLocalCallback>
bool DecodeDebugLocalInfo(uint32_t registers_size,
uint32_t ins_size,
@@ -885,8 +884,7 @@
uint32_t debug_info_offset,
bool is_static,
uint32_t method_idx,
- NewLocalCallback new_local,
- void* context) const;
+ const NewLocalCallback& new_local) const;
// Returns false if there is no debugging information or if it cannot be decoded.
template<typename DexDebugNewPosition, typename IndexToStringData>
diff --git a/libdexfile/dex/dex_file_loader_test.cc b/libdexfile/dex/dex_file_loader_test.cc
index 5bb01dd..5378617 100644
--- a/libdexfile/dex/dex_file_loader_test.cc
+++ b/libdexfile/dex/dex_file_loader_test.cc
@@ -480,10 +480,6 @@
EXPECT_EQ(raw->StringByTypeIdx(idx), nullptr);
}
-static void Callback(void* context ATTRIBUTE_UNUSED,
- const DexFile::LocalInfo& entry ATTRIBUTE_UNUSED) {
-}
-
TEST_F(DexFileLoaderTest, OpenDexDebugInfoLocalNullType) {
std::vector<uint8_t> dex_bytes;
std::unique_ptr<const DexFile> raw = OpenDexFileInMemoryBase64(kRawDexDebugInfoLocalNullType,
@@ -496,7 +492,7 @@
const DexFile::CodeItem* code_item = raw->GetCodeItem(raw->FindCodeItemOffset(class_def,
kMethodIdx));
CodeItemDebugInfoAccessor accessor(*raw, code_item, kMethodIdx);
- ASSERT_TRUE(accessor.DecodeDebugLocalInfo(true, 1, Callback, nullptr));
+ ASSERT_TRUE(accessor.DecodeDebugLocalInfo(true, 1, VoidFunctor()));
}
} // namespace art
diff --git a/openjdkjvmti/ti_method.cc b/openjdkjvmti/ti_method.cc
index 742a9fa..2958941 100644
--- a/openjdkjvmti/ti_method.cc
+++ b/openjdkjvmti/ti_method.cc
@@ -206,76 +206,59 @@
return ERR(ABSENT_INFORMATION);
}
- struct LocalVariableContext {
- explicit LocalVariableContext(jvmtiEnv* jenv) : env_(jenv), variables_(), err_(OK) {}
+ std::vector<jvmtiLocalVariableEntry> variables;
+ jvmtiError err = OK;
- static void Callback(void* raw_ctx, const art::DexFile::LocalInfo& entry) {
- reinterpret_cast<LocalVariableContext*>(raw_ctx)->Insert(entry);
+ auto release = [&](jint* out_entry_count_ptr, jvmtiLocalVariableEntry** out_table_ptr) {
+ jlong table_size = sizeof(jvmtiLocalVariableEntry) * variables.size();
+ if (err != OK ||
+ (err = env->Allocate(table_size,
+ reinterpret_cast<unsigned char**>(out_table_ptr))) != OK) {
+ for (jvmtiLocalVariableEntry& e : variables) {
+ env->Deallocate(reinterpret_cast<unsigned char*>(e.name));
+ env->Deallocate(reinterpret_cast<unsigned char*>(e.signature));
+ env->Deallocate(reinterpret_cast<unsigned char*>(e.generic_signature));
+ }
+ return err;
}
-
- void Insert(const art::DexFile::LocalInfo& entry) {
- if (err_ != OK) {
- return;
- }
- JvmtiUniquePtr<char[]> name_str = CopyString(env_, entry.name_, &err_);
- if (err_ != OK) {
- return;
- }
- JvmtiUniquePtr<char[]> sig_str = CopyString(env_, entry.descriptor_, &err_);
- if (err_ != OK) {
- return;
- }
- JvmtiUniquePtr<char[]> generic_sig_str = CopyString(env_, entry.signature_, &err_);
- if (err_ != OK) {
- return;
- }
- variables_.push_back({
- .start_location = static_cast<jlocation>(entry.start_address_),
- .length = static_cast<jint>(entry.end_address_ - entry.start_address_),
- .name = name_str.release(),
- .signature = sig_str.release(),
- .generic_signature = generic_sig_str.release(),
- .slot = entry.reg_,
- });
- }
-
- jvmtiError Release(jint* out_entry_count_ptr, jvmtiLocalVariableEntry** out_table_ptr) {
- jlong table_size = sizeof(jvmtiLocalVariableEntry) * variables_.size();
- if (err_ != OK ||
- (err_ = env_->Allocate(table_size,
- reinterpret_cast<unsigned char**>(out_table_ptr))) != OK) {
- Cleanup();
- return err_;
- } else {
- *out_entry_count_ptr = variables_.size();
- memcpy(*out_table_ptr, variables_.data(), table_size);
- return OK;
- }
- }
-
- void Cleanup() {
- for (jvmtiLocalVariableEntry& e : variables_) {
- env_->Deallocate(reinterpret_cast<unsigned char*>(e.name));
- env_->Deallocate(reinterpret_cast<unsigned char*>(e.signature));
- env_->Deallocate(reinterpret_cast<unsigned char*>(e.generic_signature));
- }
- }
-
- jvmtiEnv* env_;
- std::vector<jvmtiLocalVariableEntry> variables_;
- jvmtiError err_;
+ *out_entry_count_ptr = variables.size();
+ memcpy(*out_table_ptr, variables.data(), table_size);
+ return OK;
};
- LocalVariableContext context(env);
+ auto visitor = [&](const art::DexFile::LocalInfo& entry) {
+ if (err != OK) {
+ return;
+ }
+ JvmtiUniquePtr<char[]> name_str = CopyString(env, entry.name_, &err);
+ if (err != OK) {
+ return;
+ }
+ JvmtiUniquePtr<char[]> sig_str = CopyString(env, entry.descriptor_, &err);
+ if (err != OK) {
+ return;
+ }
+ JvmtiUniquePtr<char[]> generic_sig_str = CopyString(env, entry.signature_, &err);
+ if (err != OK) {
+ return;
+ }
+ variables.push_back({
+ .start_location = static_cast<jlocation>(entry.start_address_),
+ .length = static_cast<jint>(entry.end_address_ - entry.start_address_),
+ .name = name_str.release(),
+ .signature = sig_str.release(),
+ .generic_signature = generic_sig_str.release(),
+ .slot = entry.reg_,
+ });
+ };
+
if (!accessor.DecodeDebugLocalInfo(art_method->IsStatic(),
art_method->GetDexMethodIndex(),
- LocalVariableContext::Callback,
- &context)) {
+ visitor)) {
// Something went wrong with decoding the debug information. It might as well not be there.
return ERR(ABSENT_INFORMATION);
- } else {
- return context.Release(entry_count_ptr, table_ptr);
}
+ return release(entry_count_ptr, table_ptr);
}
jvmtiError MethodUtil::GetMaxLocals(jvmtiEnv* env ATTRIBUTE_UNUSED,
@@ -614,55 +597,25 @@
if (!accessor.HasCodeItem()) {
return ERR(OPAQUE_FRAME);
}
-
- struct GetLocalVariableInfoContext {
- explicit GetLocalVariableInfoContext(jint slot,
- uint32_t pc,
- std::string* out_descriptor,
- art::Primitive::Type* out_type)
- : found_(false), jslot_(slot), pc_(pc), descriptor_(out_descriptor), type_(out_type) {
- *descriptor_ = "";
- *type_ = art::Primitive::kPrimVoid;
+ bool found = false;
+ *type = art::Primitive::kPrimVoid;
+ descriptor->clear();
+ auto visitor = [&](const art::DexFile::LocalInfo& entry) {
+ if (!found &&
+ entry.start_address_ <= dex_pc &&
+ entry.end_address_ > dex_pc &&
+ entry.reg_ == slot_) {
+ found = true;
+ *type = art::Primitive::GetType(entry.descriptor_[0]);
+ *descriptor = entry.descriptor_;
}
-
- static void Callback(void* raw_ctx, const art::DexFile::LocalInfo& entry) {
- reinterpret_cast<GetLocalVariableInfoContext*>(raw_ctx)->Handle(entry);
- }
-
- void Handle(const art::DexFile::LocalInfo& entry) {
- if (found_) {
- return;
- } else if (entry.start_address_ <= pc_ &&
- entry.end_address_ > pc_ &&
- entry.reg_ == jslot_) {
- found_ = true;
- *type_ = art::Primitive::GetType(entry.descriptor_[0]);
- *descriptor_ = entry.descriptor_;
- }
- return;
- }
-
- bool found_;
- jint jslot_;
- uint32_t pc_;
- std::string* descriptor_;
- art::Primitive::Type* type_;
};
-
- GetLocalVariableInfoContext context(slot_, dex_pc, descriptor, type);
- if (!dex_file->DecodeDebugLocalInfo(accessor.RegistersSize(),
- accessor.InsSize(),
- accessor.InsnsSizeInCodeUnits(),
- accessor.DebugInfoOffset(),
- method->IsStatic(),
- method->GetDexMethodIndex(),
- GetLocalVariableInfoContext::Callback,
- &context) || !context.found_) {
+ if (!accessor.DecodeDebugLocalInfo(method->IsStatic(), method->GetDexMethodIndex(), visitor) ||
+ !found) {
// Something went wrong with decoding the debug information. It might as well not be there.
return ERR(INVALID_SLOT);
- } else {
- return OK;
}
+ return OK;
}
jvmtiError result_;
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 7b4fa6e..b108920 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -1700,37 +1700,6 @@
void Dbg::OutputVariableTable(JDWP::RefTypeId, JDWP::MethodId method_id, bool with_generic,
JDWP::ExpandBuf* pReply) {
- struct DebugCallbackContext {
- ArtMethod* method;
- JDWP::ExpandBuf* pReply;
- size_t variable_count;
- bool with_generic;
-
- static void Callback(void* context, const DexFile::LocalInfo& entry)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- DebugCallbackContext* pContext = reinterpret_cast<DebugCallbackContext*>(context);
-
- uint16_t slot = entry.reg_;
- VLOG(jdwp) << StringPrintf(" %2zd: %d(%d) '%s' '%s' '%s' actual slot=%d mangled slot=%d",
- pContext->variable_count, entry.start_address_,
- entry.end_address_ - entry.start_address_,
- entry.name_, entry.descriptor_, entry.signature_, slot,
- MangleSlot(slot, pContext->method));
-
- slot = MangleSlot(slot, pContext->method);
-
- expandBufAdd8BE(pContext->pReply, entry.start_address_);
- expandBufAddUtf8String(pContext->pReply, entry.name_);
- expandBufAddUtf8String(pContext->pReply, entry.descriptor_);
- if (pContext->with_generic) {
- expandBufAddUtf8String(pContext->pReply, entry.signature_);
- }
- expandBufAdd4BE(pContext->pReply, entry.end_address_- entry.start_address_);
- expandBufAdd4BE(pContext->pReply, slot);
-
- ++pContext->variable_count;
- }
- };
ArtMethod* m = FromMethodId(method_id);
CodeItemDebugInfoAccessor accessor(m->DexInstructionDebugInfo());
@@ -1742,24 +1711,39 @@
size_t variable_count_offset = expandBufGetLength(pReply);
expandBufAdd4BE(pReply, 0);
- DebugCallbackContext context;
- context.method = m;
- context.pReply = pReply;
- context.variable_count = 0;
- context.with_generic = with_generic;
+ size_t variable_count = 0;
if (accessor.HasCodeItem()) {
- m->GetDexFile()->DecodeDebugLocalInfo(accessor.RegistersSize(),
- accessor.InsSize(),
- accessor.InsnsSizeInCodeUnits(),
- accessor.DebugInfoOffset(),
- m->IsStatic(),
- m->GetDexMethodIndex(),
- DebugCallbackContext::Callback,
- &context);
+ accessor.DecodeDebugLocalInfo(m->IsStatic(),
+ m->GetDexMethodIndex(),
+ [&](const DexFile::LocalInfo& entry)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ uint16_t slot = entry.reg_;
+ VLOG(jdwp) << StringPrintf(" %2zd: %d(%d) '%s' '%s' '%s' actual slot=%d mangled slot=%d",
+ variable_count,
+ entry.start_address_,
+ entry.end_address_ - entry.start_address_,
+ entry.name_,
+ entry.descriptor_, entry.signature_,
+ slot,
+ MangleSlot(slot, m));
+
+ slot = MangleSlot(slot, m);
+
+ expandBufAdd8BE(pReply, entry.start_address_);
+ expandBufAddUtf8String(pReply, entry.name_);
+ expandBufAddUtf8String(pReply, entry.descriptor_);
+ if (with_generic) {
+ expandBufAddUtf8String(pReply, entry.signature_);
+ }
+ expandBufAdd4BE(pReply, entry.end_address_- entry.start_address_);
+ expandBufAdd4BE(pReply, slot);
+
+ ++variable_count;
+ });
}
- JDWP::Set4BE(expandBufGetBuffer(pReply) + variable_count_offset, context.variable_count);
+ JDWP::Set4BE(expandBufGetBuffer(pReply) + variable_count_offset, variable_count);
}
void Dbg::OutputMethodReturnValue(JDWP::MethodId method_id, const JValue* return_value,
diff --git a/tools/dexanalyze/dexanalyze_strings.cc b/tools/dexanalyze/dexanalyze_strings.cc
index de5c34e..dcadb59 100644
--- a/tools/dexanalyze/dexanalyze_strings.cc
+++ b/tools/dexanalyze/dexanalyze_strings.cc
@@ -119,8 +119,25 @@
return false;
}
const uint8_t* prefix_data = &dictionary_.prefix_data_[prefix_offset];
- return memcmp(prefix_data, data, prefix_len) == 0u &&
- memcmp(suffix_data, data + prefix_len, len - prefix_len) == 0u;
+ if ((true)) {
+ return memcmp(prefix_data, data, prefix_len) == 0u &&
+ memcmp(suffix_data, data + prefix_len, len - prefix_len) == 0u;
+ } else {
+ len -= prefix_len;
+ while (prefix_len != 0u) {
+ if (*prefix_data++ != *data++) {
+ return false;
+ }
+ --prefix_len;
+ }
+ while (len != 0u) {
+ if (*suffix_data++ != *data++) {
+ return false;
+ }
+ --len;
+ }
+ return true;
+ }
}
public:
@@ -164,7 +181,6 @@
std::vector<uint32_t> string_offsets_;
};
-
// Node value = (distance from root) * (occurrences - 1).
class MatchTrie {
public: