[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:
Arnaldo Carvalho de Melo 2007-01-03 21:29:24 -02:00
parent f93f16b51a
commit bed9378b42
7 changed files with 124 additions and 110 deletions

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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,

View File

@ -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;

View File

@ -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[] = {

View File

@ -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;
}