[CLASSES]: Use just one list for classes (structs, unions, etc) and functions
Almost mirroring the DWARF on-disk linkage on memory, more to come before getting over these simplification refactorings. Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
This commit is contained in:
parent
f93f16b51a
commit
bed9378b42
95
classes.c
95
classes.c
|
@ -424,8 +424,7 @@ static struct cu *cu__new(uint32_t cu, const char *name, uint8_t addr_size)
|
|||
struct cu *self = malloc(sizeof(*self));
|
||||
|
||||
if (self != NULL) {
|
||||
INIT_LIST_HEAD(&self->classes);
|
||||
INIT_LIST_HEAD(&self->functions);
|
||||
INIT_LIST_HEAD(&self->tags);
|
||||
INIT_LIST_HEAD(&self->variables);
|
||||
INIT_LIST_HEAD(&self->tool_list);
|
||||
|
||||
|
@ -446,13 +445,13 @@ static struct cu *cu__new(uint32_t cu, const char *name, uint8_t addr_size)
|
|||
|
||||
static void cu__add_tag(struct cu *self, struct tag *tag)
|
||||
{
|
||||
list_add_tail(&tag->node, &self->classes);
|
||||
list_add_tail(&tag->node, &self->tags);
|
||||
}
|
||||
|
||||
static void cu__add_function(struct cu *self, struct function *function)
|
||||
{
|
||||
function->cu = self;
|
||||
list_add_tail(&function->proto.tag.node, &self->functions);
|
||||
list_add_tail(&function->proto.tag.node, &self->tags);
|
||||
}
|
||||
|
||||
static void cu__add_variable(struct cu *self, struct variable *variable)
|
||||
|
@ -481,7 +480,7 @@ struct tag *cu__find_tag_by_id(const struct cu *self, const Dwarf_Off id)
|
|||
if (id == 0)
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(pos, &self->classes, node)
|
||||
list_for_each_entry(pos, &self->tags, node)
|
||||
if (pos->id == id)
|
||||
return pos;
|
||||
|
||||
|
@ -495,7 +494,7 @@ struct class *cu__find_class_by_name(const struct cu *self, const char *name)
|
|||
if (name == NULL)
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(pos, &self->classes, node) {
|
||||
list_for_each_entry(pos, &self->tags, node) {
|
||||
struct class *class;
|
||||
|
||||
if (pos->tag != DW_TAG_structure_type)
|
||||
|
@ -592,26 +591,19 @@ static void cus__add_fwd_decl(struct cus *self, struct class *class)
|
|||
struct function *cu__find_function_by_name(const struct cu *self,
|
||||
const char *name)
|
||||
{
|
||||
struct function *pos;
|
||||
struct tag *pos;
|
||||
struct function *fpos;
|
||||
|
||||
if (name == NULL)
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(pos, &self->functions, proto.tag.node)
|
||||
if (pos->name != NULL && strcmp(pos->name, name) == 0)
|
||||
return pos;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct function *cu__find_function_by_id(const struct cu *self,
|
||||
const Dwarf_Off id)
|
||||
{
|
||||
struct function *pos;
|
||||
|
||||
list_for_each_entry(pos, &self->functions, proto.tag.node)
|
||||
if (pos->proto.tag.id == id)
|
||||
return pos;
|
||||
list_for_each_entry(pos, &self->tags, node) {
|
||||
if (pos->tag != DW_TAG_subprogram)
|
||||
continue;
|
||||
fpos = tag__function(pos);
|
||||
if (fpos->name != NULL && strcmp(fpos->name, name) == 0)
|
||||
return fpos;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1321,8 +1313,7 @@ struct class_member *class__find_member_by_name(const struct class *self,
|
|||
static void lexblock__account_inline_expansions(struct lexblock *self,
|
||||
const struct cu *cu)
|
||||
{
|
||||
struct function *type;
|
||||
struct tag *pos;
|
||||
struct tag *pos, *type;
|
||||
|
||||
if (self->nr_inline_expansions == 0)
|
||||
return;
|
||||
|
@ -1335,10 +1326,12 @@ static void lexblock__account_inline_expansions(struct lexblock *self,
|
|||
} else if (pos->tag != DW_TAG_inlined_subroutine)
|
||||
continue;
|
||||
|
||||
type = cu__find_function_by_id(cu, pos->type);
|
||||
type = cu__find_tag_by_id(cu, pos->type);
|
||||
if (type != NULL) {
|
||||
type->cu_total_nr_inline_expansions++;
|
||||
type->cu_total_size_inline_expansions +=
|
||||
struct function *ftype = tag__function(type);
|
||||
|
||||
ftype->cu_total_nr_inline_expansions++;
|
||||
ftype->cu_total_size_inline_expansions +=
|
||||
tag__inline_expansion(pos)->size;
|
||||
}
|
||||
|
||||
|
@ -1347,12 +1340,16 @@ static void lexblock__account_inline_expansions(struct lexblock *self,
|
|||
|
||||
void cu__account_inline_expansions(struct cu *self)
|
||||
{
|
||||
struct function *pos;
|
||||
struct tag *pos;
|
||||
struct function *fpos;
|
||||
|
||||
list_for_each_entry(pos, &self->functions, proto.tag.node) {
|
||||
lexblock__account_inline_expansions(&pos->lexblock, self);
|
||||
self->nr_inline_expansions += pos->lexblock.nr_inline_expansions;
|
||||
self->size_inline_expansions += pos->lexblock.size_inline_expansions;
|
||||
list_for_each_entry(pos, &self->tags, node) {
|
||||
if (pos->tag != DW_TAG_subprogram)
|
||||
continue;
|
||||
fpos = tag__function(pos);
|
||||
lexblock__account_inline_expansions(&fpos->lexblock, self);
|
||||
self->nr_inline_expansions += fpos->lexblock.nr_inline_expansions;
|
||||
self->size_inline_expansions += fpos->lexblock.size_inline_expansions;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1397,8 +1394,9 @@ static void function__tag_print(const struct tag *tag, const struct cu *cu,
|
|||
switch (tag->tag) {
|
||||
case DW_TAG_inlined_subroutine: {
|
||||
const struct inline_expansion *exp = vtag;
|
||||
const struct function *alias =
|
||||
cu__find_function_by_id(cu, exp->tag.type);
|
||||
const struct tag *talias =
|
||||
cu__find_tag_by_id(cu, exp->tag.type);
|
||||
const struct function *alias = tag__function(talias);
|
||||
|
||||
assert(alias != NULL);
|
||||
printf("%.*s", indent, tabs);
|
||||
|
@ -1716,14 +1714,15 @@ int cu__for_each_tag(struct cu *self,
|
|||
int (*iterator)(struct tag *tag, struct cu *cu,
|
||||
void *cookie),
|
||||
void *cookie,
|
||||
struct tag *(*filter)(struct tag *tag, struct cu *cu))
|
||||
struct tag *(*filter)(struct tag *tag, struct cu *cu,
|
||||
void *cookie))
|
||||
{
|
||||
struct tag *pos;
|
||||
|
||||
list_for_each_entry(pos, &self->classes, node) {
|
||||
list_for_each_entry(pos, &self->tags, node) {
|
||||
struct tag *tag = pos;
|
||||
if (filter != NULL) {
|
||||
tag = filter(pos, self);
|
||||
tag = filter(pos, self, cookie);
|
||||
if (tag == NULL)
|
||||
continue;
|
||||
}
|
||||
|
@ -1733,28 +1732,6 @@ int cu__for_each_tag(struct cu *self,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int cu__for_each_function(struct cu *cu,
|
||||
int (*iterator)(struct function *func, void *cookie),
|
||||
void *cookie,
|
||||
struct function *(*filter)(struct function *function,
|
||||
void *cookie))
|
||||
{
|
||||
|
||||
struct function *pos;
|
||||
|
||||
list_for_each_entry(pos, &cu->functions, proto.tag.node) {
|
||||
struct function *function = pos;
|
||||
if (filter != NULL) {
|
||||
function = filter(pos, cookie);
|
||||
if (function == NULL)
|
||||
continue;
|
||||
}
|
||||
if (iterator(function, cookie))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cus__for_each_cu(struct cus *self,
|
||||
int (*iterator)(struct cu *cu, void *cookie),
|
||||
void *cookie,
|
||||
|
|
19
classes.h
19
classes.h
|
@ -26,8 +26,7 @@ struct cus {
|
|||
|
||||
struct cu {
|
||||
struct list_head node;
|
||||
struct list_head classes;
|
||||
struct list_head functions;
|
||||
struct list_head tags;
|
||||
struct list_head variables;
|
||||
struct list_head tool_list; /* To be used by tools such as ctracer */
|
||||
const char *name;
|
||||
|
@ -161,6 +160,11 @@ struct function {
|
|||
struct class *class_to_diff;
|
||||
};
|
||||
|
||||
static inline struct function *tag__function(const struct tag *self)
|
||||
{
|
||||
return (struct function *)self;
|
||||
}
|
||||
|
||||
struct parameter {
|
||||
struct tag tag;
|
||||
char *name;
|
||||
|
@ -243,13 +247,8 @@ extern int cu__for_each_tag(struct cu *self,
|
|||
void *cookie),
|
||||
void *cookie,
|
||||
struct tag *(*filter)(struct tag *tag,
|
||||
struct cu *cu));
|
||||
extern int cu__for_each_function(struct cu *cu,
|
||||
int (*iterator)(struct function *func,
|
||||
void *cookie),
|
||||
void *cookie,
|
||||
struct function *(*filter)(struct function *function,
|
||||
void *cookie));
|
||||
struct cu *cu,
|
||||
void *cookie));
|
||||
extern void cus__for_each_cu(struct cus *self,
|
||||
int (*iterator)(struct cu *cu,
|
||||
void *cookie),
|
||||
|
@ -261,8 +260,6 @@ extern const struct class_member *
|
|||
const struct class_member *trailer,
|
||||
const size_t bit_hole_size);
|
||||
|
||||
extern struct function *cu__find_function_by_id(const struct cu *self,
|
||||
const Dwarf_Off id);
|
||||
extern struct function *cu__find_function_by_name(const struct cu *cu,
|
||||
const char *name);
|
||||
|
||||
|
|
49
codiff.c
49
codiff.c
|
@ -214,12 +214,23 @@ static int diff_class_iterator(struct tag *tag, struct cu *cu, void *new_cu)
|
|||
|
||||
static int diff_function_iterator(struct function *function, void *new_cu)
|
||||
{
|
||||
diff_function(new_cu, function);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int find_new_functions_iterator(struct function *function, void *old_cu)
|
||||
static int diff_tag_iterator(struct tag *tag, struct cu *cu, void *new_cu)
|
||||
{
|
||||
if (tag->tag == DW_TAG_structure_type)
|
||||
diff_struct(new_cu, tag__class(tag));
|
||||
else if (tag->tag == DW_TAG_subprogram)
|
||||
diff_function(new_cu, tag__function(tag));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int find_new_functions_iterator(struct tag *tfunction, struct cu *cu,
|
||||
void *old_cu)
|
||||
{
|
||||
struct function *function = tag__function(tfunction);
|
||||
struct function *old_function;
|
||||
|
||||
assert(function->proto.tag.tag == DW_TAG_subprogram);
|
||||
|
@ -268,16 +279,20 @@ static int find_new_classes_iterator(struct tag *tag, struct cu *cu, void *old_c
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cu_find_new_classes_iterator(struct cu *new_cu, void *old_cus)
|
||||
static int find_new_tags_iterator(struct tag *tag, struct cu *cu, void *old_cu)
|
||||
{
|
||||
if (tag->tag == DW_TAG_subprogram)
|
||||
return find_new_functions_iterator(tag, cu, old_cu);
|
||||
return find_new_classes_iterator(tag, cu, old_cu);
|
||||
}
|
||||
|
||||
static int cu_find_new_tags_iterator(struct cu *new_cu, void *old_cus)
|
||||
{
|
||||
struct cu *old_cu = cus__find_cu_by_name(old_cus, new_cu->name);
|
||||
|
||||
if (old_cu != NULL) {
|
||||
cu__for_each_tag(new_cu, find_new_classes_iterator,
|
||||
if (old_cu != NULL)
|
||||
cu__for_each_tag(new_cu, find_new_tags_iterator,
|
||||
old_cu, NULL);
|
||||
cu__for_each_function(new_cu, find_new_functions_iterator,
|
||||
old_cu, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -286,10 +301,8 @@ static int cu_diff_iterator(struct cu *cu, void *new_cus)
|
|||
{
|
||||
struct cu *new_cu = cus__find_cu_by_name(new_cus, cu->name);
|
||||
|
||||
if (new_cu != NULL) {
|
||||
cu__for_each_tag(cu, diff_class_iterator, new_cu, NULL);
|
||||
cu__for_each_function(cu, diff_function_iterator, new_cu, NULL);
|
||||
}
|
||||
if (new_cu != NULL)
|
||||
cu__for_each_tag(cu, diff_tag_iterator, new_cu, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -404,9 +417,12 @@ static void show_diffs_structure(const struct class *structure)
|
|||
print_terse_type_changes(structure);
|
||||
}
|
||||
|
||||
static int show_function_diffs_iterator(struct function *function, void *new_cu)
|
||||
static int show_function_diffs_iterator(struct tag *tag, struct cu *cu,
|
||||
void *new_cu)
|
||||
{
|
||||
if (function->diff != 0)
|
||||
struct function *function = tag__function(tag);
|
||||
|
||||
if (tag->tag == DW_TAG_subprogram && function->diff != 0)
|
||||
show_diffs_function(function);
|
||||
return 0;
|
||||
}
|
||||
|
@ -458,8 +474,7 @@ static int cu_show_diffs_iterator(struct cu *cu, void *cookie)
|
|||
if (cu->nr_functions_changed != 0 && show_function_diffs) {
|
||||
total_nr_functions_changed += cu->nr_functions_changed;
|
||||
|
||||
cu__for_each_function(cu, show_function_diffs_iterator,
|
||||
NULL, NULL);
|
||||
cu__for_each_tag(cu, show_function_diffs_iterator, NULL, NULL);
|
||||
printf(" %u function%s changed", cu->nr_functions_changed,
|
||||
cu->nr_functions_changed > 1 ? "s" : "");
|
||||
if (cu->function_bytes_added != 0) {
|
||||
|
@ -548,7 +563,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
cus__for_each_cu(old_cus, cu_diff_iterator, new_cus, NULL);
|
||||
cus__for_each_cu(new_cus, cu_find_new_classes_iterator, old_cus, NULL);
|
||||
cus__for_each_cu(new_cus, cu_find_new_tags_iterator, old_cus, NULL);
|
||||
cus__for_each_cu(old_cus, cu_show_diffs_iterator, NULL, NULL);
|
||||
cus__for_each_cu(new_cus, cu_show_diffs_iterator, NULL, NULL);
|
||||
|
||||
|
|
25
ctracer.c
25
ctracer.c
|
@ -26,19 +26,27 @@ static void method__add(struct cu *cu, struct function *function)
|
|||
list_add(&function->tool_node, &cu->tool_list);
|
||||
}
|
||||
|
||||
static struct function *function__filter(struct function *function,
|
||||
void *cookie)
|
||||
static struct tag *function__filter(struct tag *tag, struct cu *cu, void *cookie)
|
||||
{
|
||||
if (function__inlined(function) ||
|
||||
!ftype__has_parm_of_type(&function->proto, cookie, function->cu))
|
||||
struct function *function;
|
||||
|
||||
if (tag->tag != DW_TAG_subprogram)
|
||||
return NULL;
|
||||
|
||||
return function;
|
||||
function = tag__function(tag);
|
||||
if (function__inlined(function) ||
|
||||
!ftype__has_parm_of_type(&function->proto, cookie, cu))
|
||||
return NULL;
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
static int find_methods_iterator(struct function *function, void *cookie)
|
||||
static int find_methods_iterator(struct tag *tag, struct cu *cu, void *cookie)
|
||||
{
|
||||
method__add(function->cu, function);
|
||||
if (tag->tag == DW_TAG_subprogram) {
|
||||
struct function *function = tag__function(tag);
|
||||
method__add(cu, function);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -49,8 +57,7 @@ static int cu_find_methods_iterator(struct cu *cu, void *cookie)
|
|||
if (target == NULL)
|
||||
return 0;
|
||||
|
||||
return cu__for_each_function(cu, find_methods_iterator, target,
|
||||
function__filter);
|
||||
return cu__for_each_tag(cu, find_methods_iterator, target, function__filter);
|
||||
}
|
||||
|
||||
static int function__emit_kprobes(const struct function *self,
|
||||
|
|
2
pahole.c
2
pahole.c
|
@ -186,7 +186,7 @@ static struct tag *tag__to_struct(struct tag *tag, const struct cu *cu)
|
|||
return typedef_alias ?: tag;
|
||||
}
|
||||
|
||||
static struct tag *tag__filter(struct tag *tag, struct cu *cu)
|
||||
static struct tag *tag__filter(struct tag *tag, struct cu *cu, void *cookie)
|
||||
{
|
||||
struct structure *str;
|
||||
struct class *class;
|
||||
|
|
41
pfunct.c
41
pfunct.c
|
@ -174,11 +174,16 @@ static void fn_stats__chkdupdef(const struct function *self,
|
|||
putchar('\n');
|
||||
}
|
||||
|
||||
static struct function *function__filter(struct function *function,
|
||||
void *cookie)
|
||||
static struct tag *function__filter(struct tag *tag, struct cu *cu,
|
||||
void *cookie)
|
||||
{
|
||||
struct function *function;
|
||||
struct fn_stats *fstats;
|
||||
|
||||
if (tag->tag != DW_TAG_subprogram)
|
||||
return NULL;
|
||||
|
||||
function = tag__function(tag);
|
||||
if (function->name == NULL)
|
||||
return NULL;
|
||||
|
||||
|
@ -201,28 +206,34 @@ static struct function *function__filter(struct function *function,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return function;
|
||||
return tag;
|
||||
}
|
||||
|
||||
static int unique_iterator(struct function *function, void *cookie)
|
||||
static int unique_iterator(struct tag *tag, struct cu *cu, void *cookie)
|
||||
{
|
||||
fn_stats__add(function);
|
||||
if (tag->tag == DW_TAG_subprogram)
|
||||
fn_stats__add(tag__function(tag));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cu_unique_iterator(struct cu *cu, void *cookie)
|
||||
{
|
||||
cu__account_inline_expansions(cu);
|
||||
return cu__for_each_function(cu, unique_iterator, cookie,
|
||||
function__filter);
|
||||
return cu__for_each_tag(cu, unique_iterator, cookie, function__filter);
|
||||
}
|
||||
|
||||
static int class_iterator(struct function *function, void *cookie)
|
||||
static int class_iterator(struct tag *tag, struct cu *cu, void *cookie)
|
||||
{
|
||||
struct function *function;
|
||||
|
||||
if (tag->tag != DW_TAG_subprogram)
|
||||
return 0;
|
||||
|
||||
function = tag__function(tag);
|
||||
if (function->inlined)
|
||||
return 0;
|
||||
|
||||
if (ftype__has_parm_of_type(&function->proto, cookie, function->cu)) {
|
||||
if (ftype__has_parm_of_type(&function->proto, cookie, cu)) {
|
||||
if (verbose)
|
||||
function__print(function, 1, 0, 0);
|
||||
else
|
||||
|
@ -238,11 +249,17 @@ static int cu_class_iterator(struct cu *cu, void *cookie)
|
|||
if (target == NULL)
|
||||
return 0;
|
||||
|
||||
return cu__for_each_function(cu, class_iterator, target, NULL);
|
||||
return cu__for_each_tag(cu, class_iterator, target, NULL);
|
||||
}
|
||||
|
||||
static int function_iterator(struct function *function, void *cookie)
|
||||
static int function_iterator(struct tag *tag, struct cu *cu, void *cookie)
|
||||
{
|
||||
struct function *function;
|
||||
|
||||
if (tag->tag != DW_TAG_subprogram)
|
||||
return 0;
|
||||
|
||||
function = tag__function(tag);
|
||||
if (function->name != NULL &&
|
||||
strcmp(function->name, cookie) == 0) {
|
||||
function__print(function, 1, show_variables,
|
||||
|
@ -254,7 +271,7 @@ static int function_iterator(struct function *function, void *cookie)
|
|||
|
||||
static int cu_function_iterator(struct cu *cu, void *cookie)
|
||||
{
|
||||
return cu__for_each_function(cu, function_iterator, cookie, NULL);
|
||||
return cu__for_each_tag(cu, function_iterator, cookie, NULL);
|
||||
}
|
||||
|
||||
static struct option long_options[] = {
|
||||
|
|
|
@ -125,6 +125,8 @@ static int refcnt_tag_iterator(struct tag *tag, struct cu *cu, void *cookie)
|
|||
{
|
||||
if (tag->tag == DW_TAG_structure_type)
|
||||
class__find_holes(tag__class(tag));
|
||||
else if (tag->tag == DW_TAG_structure_type)
|
||||
refcnt_function_iterator(tag__function(tag), cookie);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -132,7 +134,6 @@ static int refcnt_tag_iterator(struct tag *tag, struct cu *cu, void *cookie)
|
|||
static int cu_refcnt_iterator(struct cu *cu, void *cookie)
|
||||
{
|
||||
cu__for_each_tag(cu, refcnt_tag_iterator, cookie, NULL);
|
||||
cu__for_each_function(cu, refcnt_function_iterator, cookie, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue