From: José Fonseca Date: Fri, 26 Nov 2010 14:14:45 +0000 (+0000) Subject: More efficient bitmask representation. X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;h=d35973cb47a75034dbbb64e9b0a91fcb4cc971d6;p=apitrace More efficient bitmask representation. --- diff --git a/trace.py b/trace.py index 388729a..95e84b5 100644 --- a/trace.py +++ b/trace.py @@ -81,18 +81,14 @@ class DumpDeclarator(stdapi.OnceVisitor): print def visit_bitmask(self, bitmask): - print 'static void __traceBitmask%s(%s value) {' % (bitmask.id, bitmask.type) - print ' Trace::BeginBitmask();' + print 'static const Trace::BitmaskVal __bitmask%s_vals[] = {' % (bitmask.id) for value in bitmask.values: - print ' if((value & %s) == %s) {' % (value, value) - print ' Trace::LiteralNamedConstant("%s", %s);' % (value, value) - print ' value &= ~%s;' % value - print ' }' - print ' if(value) {' - dump_instance(bitmask.type, "value"); - print ' }' - print ' Trace::EndBitmask();' - print '}' + print ' {"%s", %s},' % (value, value) + print '};' + print + print 'static const Trace::BitmaskSig __bitmask%s_sig = {' % (bitmask.id) + print ' %u, %u, __bitmask%s_vals' % (int(bitmask.id), len(bitmask.values), bitmask.id) + print '};' print def visit_pointer(self, pointer): @@ -150,7 +146,7 @@ class DumpImplementer(stdapi.Visitor): print ' __traceEnum%s(%s);' % (enum.id, instance) def visit_bitmask(self, bitmask, instance): - print ' __traceBitmask%s(%s);' % (bitmask.id, instance) + print ' Trace::LiteralBitmask(__bitmask%s_sig, %s);' % (bitmask.id, instance) def visit_pointer(self, pointer, instance): print ' if(%s) {' % instance diff --git a/trace_model.cpp b/trace_model.cpp index 760093c..e6ec467 100644 --- a/trace_model.cpp +++ b/trace_model.cpp @@ -59,6 +59,10 @@ void Const::visit(Visitor &visitor) { visitor.visit(this); } +void Bitmask::visit(Visitor &visitor) { + visitor.visit(this); +} + void Array::visit(Visitor &visitor) { visitor.visit(this); } @@ -129,6 +133,29 @@ public: os << literal << node->name << normal; } + void visit(Bitmask *bitmask) { + unsigned long long value = bitmask->value; + const Bitmask::Signature *sig = bitmask->sig; + bool first = true; + for (Bitmask::Signature::const_iterator it = sig->begin(); value != 0 && it != sig->end(); ++it) { + assert(it->second); + if ((value & it->second) == it->second) { + if (!first) { + os << " | "; + } + os << literal << it->first << normal; + value &= ~it->second; + first = false; + } + } + if (value || first) { + if (!first) { + os << " | "; + } + os << literal << std::hex << value << std::dec << normal; + } + } + void visit(Array *array) { if (array->values.size() == 1) { os << "&"; diff --git a/trace_model.hpp b/trace_model.hpp index 8a87e0f..0bcd180 100644 --- a/trace_model.hpp +++ b/trace_model.hpp @@ -171,6 +171,20 @@ public: }; +class Bitmask : public UInt +{ +public: + typedef std::pair Pair; + typedef std::vector Signature; + + Bitmask(const Signature *_sig, unsigned long long _value) : UInt(_value), sig(_sig) {} + + void visit(Visitor &visitor); + + const Signature *sig; +}; + + class Array : public Value { public: @@ -211,6 +225,7 @@ public: virtual void visit(Float *) {assert(0);} virtual void visit(String *) {assert(0);} virtual void visit(Const *) {assert(0);} + virtual void visit(Bitmask *bitmask) {visit(static_cast(bitmask));} virtual void visit(Array *) {assert(0);} virtual void visit(Blob *) {assert(0);} diff --git a/trace_parser.hpp b/trace_parser.hpp index 850dc8d..b77fc3e 100644 --- a/trace_parser.hpp +++ b/trace_parser.hpp @@ -56,6 +56,9 @@ protected: typedef std::map callmap; callmap calls; + typedef std::map BitmaskMap; + BitmaskMap bitmasks; + unsigned next_call_no; public: @@ -235,30 +238,26 @@ public: } Value *parse_bitmask() { - unsigned long long value = 0; - int c; - do { - c = read_byte(); - switch(c) { - case Trace::TYPE_SINT: - value |= -(signed long long)read_uint(); - break; - case Trace::TYPE_UINT: - value |= read_uint(); - break; - case Trace::TYPE_CONST: - read_name(); - break; - case Trace::TYPE_NULL: - goto done; - default: - std::cerr << "error: uexpected type " << c << "\n"; - assert(0); - return NULL; - } - } while(true); -done: - return new UInt(value); + size_t id = read_uint(); + Bitmask::Signature *sig; + BitmaskMap::const_iterator it = bitmasks.find(id); + if (it == bitmasks.end()) { + size_t size = read_uint(); + sig = new Bitmask::Signature(size); + for (Bitmask::Signature::iterator it = sig->begin(); it != sig->end(); ++it) { + it->first = read_string(); + it->second = read_uint(); + assert(it->second); + } + bitmasks[id] = sig; + } else { + sig = it->second; + } + assert(sig); + + unsigned long long value = read_uint(); + + return new Bitmask(sig, value); } Value *parse_array(void) { diff --git a/trace_write.cpp b/trace_write.cpp index 054303b..912824e 100644 --- a/trace_write.cpp +++ b/trace_write.cpp @@ -303,6 +303,22 @@ void LiteralNamedConstant(const char *name, long long value) { LiteralSInt(value); } +static std::map bitmasks; + +void LiteralBitmask(const BitmaskSig &bitmask, unsigned long long value) { + WriteByte(Trace::TYPE_BITMASK); + WriteUInt(bitmask.id); + if (!bitmasks[bitmask.id]) { + WriteUInt(bitmask.count); + for (unsigned i = 0; i < bitmask.count; ++i) { + WriteString(bitmask.values[i].name); + WriteUInt(bitmask.values[i].value); + } + bitmasks[bitmask.id] = true; + } + WriteUInt(value); +} + void LiteralNull(void) { WriteByte(Trace::TYPE_NULL); } diff --git a/trace_write.hpp b/trace_write.hpp index 7b494e4..faa36a5 100644 --- a/trace_write.hpp +++ b/trace_write.hpp @@ -23,11 +23,24 @@ * **************************************************************************/ -#ifndef _TRACE_HPP_ -#define _TRACE_HPP_ +#ifndef _TRACE_WRITE_HPP_ +#define _TRACE_WRITE_HPP_ namespace Trace { + typedef unsigned Id; + + struct BitmaskVal { + const char *name; + unsigned long long value; + }; + + struct BitmaskSig { + Id id; + unsigned count; + const BitmaskVal *values; + }; + void Open(void); void Close(void); @@ -55,9 +68,6 @@ namespace Trace { void BeginMember(const char *name); inline void EndMember(void) {} - void BeginBitmask(void); - void EndBitmask(void); - void LiteralBool(bool value); void LiteralSInt(signed long long value); void LiteralUInt(unsigned long long value); @@ -68,10 +78,11 @@ namespace Trace { void LiteralWString(const wchar_t *str); void LiteralBlob(const void *data, size_t size); void LiteralNamedConstant(const char *name, long long value); + void LiteralBitmask(const BitmaskSig &bitmask, unsigned long long value); void LiteralNull(void); void LiteralOpaque(const void *ptr); void Abort(void); } -#endif /* _TRACE_HPP_ */ +#endif /* _TRACE_WRITE_HPP_ */