[xml-writter] Avoid using RTTI when dynamically hashing types
authorDodji Seketeli <dodji@redhat.com>
Mon, 8 Jul 2019 14:53:52 +0000 (16:53 +0200)
committerDodji Seketeli <dodji@redhat.com>
Mon, 8 Jul 2019 14:59:03 +0000 (16:59 +0200)
When we dynamically hash types in the abixml writter, we use
hash_type_or_decl.  This function uses runtime type identification to
determine if the (type) artifact is a decl or a type, and based on
that, choose how to compute its hash value.  Profiling shows that
using the RTTI in hash_type_or_decl at this point is a hotspot.

Because we know that the type ABI is a *type*, we obviously can avoid
using RTTI there.

The patch thus implements a hash_type function, and uses that in the
xml writter.  Emitting the abixml output is faster with this patch.

* include/abg-fwd.h (hash_type): Declare new function.
* src/abg-ir.cc (hash_type): Define new function.
* src/abg-writer.cc (type_hasher::operator()): Use the new
  hash_type rather than the old hash_type_or_decl.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
include/abg-fwd.h
src/abg-ir.cc
src/abg-writer.cc

index 8e45a25e3bdfb4091ccd42f056c56280bea4ca9c..0ea8b2b963bb7cb1ce67cc8443e892cfccf71da9 100644 (file)
@@ -1263,6 +1263,9 @@ type_has_sub_type_changes(type_base_sptr t_v1,
 void
 keep_type_alive(type_base_sptr t);
 
+size_t
+hash_type(const type_base *t);
+
 size_t
 hash_type_or_decl(const type_or_decl_base *);
 
index 106258be54a69f7dbf2eb7b232e2fa8ce05b0079..19b808265ae7f7639ec0d03cf6823bef7db75a48 100644 (file)
@@ -21697,6 +21697,58 @@ hash_type_or_decl(const type_or_decl_base *tod)
   return result;
 }
 
+/// Hash an ABI artifact that is either a type.
+///
+/// This function intends to provides the fastest possible hashing for
+/// types while being completely correct.
+///
+/// Note that if the type artifact has a canonical type, the hash
+/// value is going to be the pointer value of the canonical type.
+/// Otherwise, this function computes a hash value for the type by
+/// recursively walking the type members.  This last code path is
+/// possibly *very* slow and should only be used when only handful of
+/// types are going to be hashed.
+///
+/// @param t the type or decl to hash.
+///
+/// @return the resulting hash value.
+size_t
+hash_type(const type_base *t)
+{
+  size_t result = 0;
+
+  // If the type has a canonical type, then use the pointer value
+  // as a hash.  This is the fastest we can get.
+  if (type_base* ct = t->get_naked_canonical_type())
+    result = reinterpret_cast<size_t>(ct);
+  else if (const class_decl* cl = is_class_type(t))
+    {
+      if (cl->get_is_declaration_only()
+         && cl->get_naked_definition_of_declaration())
+       // The is a declaration-only class, so it has no canonical
+       // type; but then it's class definition has one.  Let's
+       // use that one.
+       return hash_type(cl->get_naked_definition_of_declaration());
+      else
+       {
+         // The class really has no canonical type, let's use the
+         // slow path of hashing the class recursively.  Well
+         // it's not that slow as the hash value is quickly going
+         // to result to zero anyway.
+         type_base::dynamic_hash hash;
+         result = hash(t);
+       }
+    }
+  else
+    {
+      // Let's use the slow path of hashing the class recursively.
+      type_base::dynamic_hash hash;
+      result = hash(t);
+    }
+
+  return result;
+}
+
 /// Hash an ABI artifact that is either a type of a decl.
 ///
 /// @param tod the ABI artifact to hash.
index 2c9085be86afbec63013b61ec58df507cafc03bc..0aaa03d42949a6e9df87b0bd6c1f7c622af6c127 100644 (file)
@@ -134,7 +134,7 @@ struct type_hasher
 {
   size_t
   operator()(const type_base* t) const
-  {return hash_type_or_decl(t);}
+  {return hash_type(t);}
 }; // end struct type_hasher
 
 /// A convenience typedef for a map that associates a pointer to type