Implement a poor-man's RTTI for performance

Profiling showed that a number of use of dynamic_cast are a speed
bottleneck.

This patch implements a poor-man's RTTI that allows us to implement a
form of dynamic_cast that is specific to the types of the internal
reprenstation that are in the namespace abigail::ir.  It speeds up
things greatly.

Basically, the base type of all ABI artifacts
(abigail::ir::type_or_decl_base) now contains three new data members.
The first one contains a bitmap that identifies the type of artifact.
The second one contains a pointer to the dynamic type sub-object of
the current instance of the artifact.  The last one contains either a
pointer to the type_base sub-object of the current instance of ABI
artifact if it's a type, or a pointer to the type_decl sub-object of
the current instance.

Together these three data members allow the patch to implement the
abigail::ir::{is_type(), is_decl(), is_<type_kind>_type} functions
that we need to make the code base noticeably faster when using abidw
on a big vmlinux binary.

	* include/abg-fwd.h (is_type_decl): Replace the overloads
	that takes a type_base* and/or a decl_base* by one that takes a
	type_or_decl_base*.
	* include/abg-ir.h (type_or_decl_base::type_or_decl_kind): Define
	new enum.
	(type_or_decl_base::{kind, runtime_type_instance,
	type_or_decl_base_pointer}): Declare new accessors.
	(operator{|,|=,&,&=): Declare new operators for the new
	type_or_decl_base::type_or_decl_kind enum.
	(global_scope::global_scope): Move the definition of this
	constructor to ...
	* src/abg-ir.cc (global_scope::global_scope): ... here.
	(type_or_decl_base::priv::{kind_, rtti_, type_or_decl_ptr_}):
	Add new data members.
	(type_or_decl_base::priv::priv): Take a
	type_or_decl_base::type_or_decl_kind enum.
	(type_or_decl_base::priv::kind): Define new accessors.
	(operator{|,|=,&,&=): Define new operators for the new
	type_or_decl_base::type_or_decl_kind enum.
	(type_or_decl_base::type_or_decl_base): Take a
	type_or_decl_base::type_or_decl_kind enum.
	(type_or_decl_base::{kind, runtime_type_instance,
	type_or_decl_base_pointer}): Define new accessors.
	(decl_base::decl_base, scope_decl::scope_decl)
	(type_base::type_base, scope_type_decl::scope_type_decl)
	(class_or_union::class_or_union) : Adjust to set the runtime type
	identifier of the instances of these types.
	(global_scope::global_scope, type_decl::type_decl)
	(qualified_type_def::qualified_type_def)
	(pointer_type_def::pointer_type_def)
	(reference_type_def::reference_type_def
	array_type_def::subrange_type::subrange_type)
	(array_type_def::array_type_def, enum_type_decl::enum_type_decl)
	(typedef_decl::typedef_decl, var_decl::var_decl)
	(function_type::function_type, method_type::method_type)
	(function_decl::function_decl)
	(function_decl::parameter::parameter, method_decl::method_decl)
	(class_decl::class_decl, class_decl::base_spec::base_spec)
	(union_decl::union_decl, template_decl::template_decl)
	(type_tparameter::type_tparameter)
	(non_type_tparameter::non_type_tparameter)
	(template_tparameter::template_tparameter)
	(type_composition::type_composition)
	(function_tdecl::function_tdecl, function_tdecl::function_tdecl)
	(class_tdecl::class_tdecl):
	Likewise and call runtime_type_instance() here to set the runtime
	type instance pointers of the current instance.
	(is_decl, is_type, is_class_type, is_pointer_type): Adjust to use
	the new poor-man's rtti machinery.
	(is_type_decl): Replace the overloads that takes a type_base*
	and/or a decl_base* by one that takes a type_or_decl_base*.
	(pointer_type_def::operator==, class_decl::operator==): Use the
	poor-man's rtti machinery to replace dynamic_cast.
	hash_type_or_decl: Replace dynamic_cast<const type_base> by
	is_type() and dynamic_cast<const decl_base*> by is_decl().

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
Dodji Seketeli 2019-07-08 15:37:18 +02:00
parent 35312fa92a
commit c940a229c9
3 changed files with 609 additions and 131 deletions

View File

@ -408,13 +408,10 @@ bool
is_anonymous_type(const type_base_sptr&);
const type_decl*
is_type_decl(const type_base*);
is_type_decl(const type_or_decl_base*);
type_decl_sptr
is_type_decl(const type_base_sptr&);
type_decl_sptr
is_type_decl(const decl_base_sptr&);
is_type_decl(const type_or_decl_base_sptr&);
typedef_decl_sptr
is_typedef(const type_or_decl_base_sptr);

View File

@ -1167,13 +1167,66 @@ class type_or_decl_base : public ir_traversable_base
protected:
/// This is a bitmap type which instance is meant to contain the
/// runtime type of a given ABI artifact. Bits of the identifiers
/// of the type of a given artifact as well as the types it inherits
/// from are to be set to 1.
enum type_or_decl_kind
{
ABSTRACT_TYPE_OR_DECL,
ABSTRACT_DECL_BASE = 1,
ABSTRACT_SCOPE_DECL = 1 << 1,
GLOBAL_SCOPE_DECL = 1 << 2,
NAMESPACE_DECL = 1 << 3,
VAR_DECL = 1 << 4,
FUNCTION_DECL = 1 << 5,
FUNCTION_PARAMETER_DECL = 1 << 6,
METHOD_DECL = 1 << 7,
TEMPLATE_DECL = 1 << 8,
ABSTRACT_TYPE_BASE = 1 << 9,
ABSTRACT_SCOPE_TYPE_DECL = 1 << 10,
BASIC_TYPE = 1 << 11,
QUALIFIED_TYPE = 1 << 12,
POINTER_TYPE = 1 << 13,
REFERENCE_TYPE = 1 << 14,
ARRAY_TYPE = 1 << 15,
ENUM_TYPE = 1 << 16,
TYPEDEF_TYPE = 1 << 17,
CLASS_TYPE = 1 << 18,
UNION_TYPE = 1 << 19,
FUNCTION_TYPE = 1 << 20,
METHOD_TYPE = 1 << 21,
}; // end enum type_or_decl_kind
enum type_or_decl_kind
kind() const;
void
kind(enum type_or_decl_kind);
const void*
runtime_type_instance() const;
void*
runtime_type_instance();
void
runtime_type_instance(void*);
const void*
type_or_decl_base_pointer() const;
void*
type_or_decl_base_pointer();
bool hashing_started() const;
void hashing_started(bool) const;
public:
type_or_decl_base(const environment*);
type_or_decl_base(const environment*,
enum type_or_decl_kind k = ABSTRACT_TYPE_OR_DECL);
type_or_decl_base(const type_or_decl_base&);
@ -1212,8 +1265,52 @@ public:
virtual string
get_pretty_representation(bool internal = false,
bool qualified_name = true) const = 0;
friend type_or_decl_base::type_or_decl_kind
operator|(type_or_decl_base::type_or_decl_kind,
type_or_decl_base::type_or_decl_kind);
friend type_or_decl_base::type_or_decl_kind&
operator|=(type_or_decl_base::type_or_decl_kind&,
type_or_decl_base::type_or_decl_kind);
friend type_or_decl_base::type_or_decl_kind
operator&(type_or_decl_base::type_or_decl_kind,
type_or_decl_base::type_or_decl_kind);
friend type_or_decl_base::type_or_decl_kind&
operator&=(type_or_decl_base::type_or_decl_kind&,
type_or_decl_base::type_or_decl_kind);
friend class_decl*
is_class_type(const type_or_decl_base*);
friend pointer_type_def*
is_pointer_type(type_or_decl_base*);
friend type_base*
is_type(const type_or_decl_base*);
friend decl_base*
is_decl(const type_or_decl_base* d);
}; // end class type_or_decl_base
type_or_decl_base::type_or_decl_kind
operator|(type_or_decl_base::type_or_decl_kind,
type_or_decl_base::type_or_decl_kind);
type_or_decl_base::type_or_decl_kind&
operator|=(type_or_decl_base::type_or_decl_kind&,
type_or_decl_base::type_or_decl_kind);
type_or_decl_base::type_or_decl_kind
operator&(type_or_decl_base::type_or_decl_kind,
type_or_decl_base::type_or_decl_kind);
type_or_decl_base::type_or_decl_kind&
operator&=(type_or_decl_base::type_or_decl_kind&,
type_or_decl_base::type_or_decl_kind);
bool
operator==(const type_or_decl_base&, const type_or_decl_base&);
@ -1590,12 +1687,7 @@ class global_scope : public scope_decl
{
translation_unit* translation_unit_;
global_scope(translation_unit *tu)
: type_or_decl_base(tu->get_environment()),
decl_base(tu->get_environment(), "", location()),
scope_decl(tu->get_environment(), "", location()),
translation_unit_(tu)
{}
global_scope(translation_unit *tu);
public:

File diff suppressed because it is too large Load Diff