From: Zack Rusin Date: Thu, 1 Sep 2011 05:50:56 +0000 (-0400) Subject: First working implementation of on-demand-loading of frames/calls. X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;h=e0df952b67f3ae38aeb0fd7e32942f8fa53ac49f;p=apitrace First working implementation of on-demand-loading of frames/calls. --- diff --git a/loadertest.cpp b/loadertest.cpp index 48bdac9..4063e76 100644 --- a/loadertest.cpp +++ b/loadertest.cpp @@ -28,7 +28,7 @@ int main(int argc, char **argv) std::vector frame = loader.frame( - 0); + loader.numberOfFrames()/2); std::vector::const_iterator itr; for (itr = frame.begin(); itr != frame.end(); ++itr) { (*itr)->dump(std::cout, true); diff --git a/trace_file.hpp b/trace_file.hpp index e3d797d..2129d1e 100644 --- a/trace_file.hpp +++ b/trace_file.hpp @@ -167,6 +167,40 @@ private: void *m_gzFile; }; +inline bool +operator<(const File::Offset &one, const File::Offset &two) +{ + return one.chunk < two.chunk || + (one.chunk == two.chunk && one.offsetInChunk < two.offsetInChunk); +} + +inline bool +operator==(const File::Offset &one, const File::Offset &two) +{ + return one.chunk == two.chunk && + one.offsetInChunk == two.offsetInChunk; +} + +inline bool +operator>=(const File::Offset &one, const File::Offset &two) +{ + return one.chunk > two.chunk || + (one.chunk == two.chunk && one.offsetInChunk >= two.offsetInChunk); +} + +inline bool +operator>(const File::Offset &one, const File::Offset &two) +{ + return two < one; +} + +inline bool +operator<=(const File::Offset &one, const File::Offset &two) +{ + return two >= one; +} + + } #endif diff --git a/trace_loader.cpp b/trace_loader.cpp index f2e6c6e..254d2cb 100644 --- a/trace_loader.cpp +++ b/trace_loader.cpp @@ -45,6 +45,11 @@ bool Loader::open(const char *filename) std::cerr << "error: failed to open " << filename << "\n"; return false; } + if (!m_parser.supportsOffsets()) { + std::cerr << "error: " < Trace::Loader::frame(int idx) +std::vector Loader::frame(int idx) { int numOfCalls = numberOfCallsInFrame(idx); if (numOfCalls) { @@ -113,13 +118,15 @@ std::vector Trace::Loader::frame(int idx) int parsedCalls = 0; while ((call = m_parser.parse_call())) { + calls[parsedCalls] = call; + ++parsedCalls; + if (isCallAFrameMarker(call)) { break; } - calls[parsedCalls] = call; - ++parsedCalls; } + assert(parsedCalls == numOfCalls); return calls; } return std::vector(); diff --git a/trace_parser.cpp b/trace_parser.cpp index 44d1786..abed4f5 100644 --- a/trace_parser.cpp +++ b/trace_parser.cpp @@ -146,22 +146,41 @@ void Parser::parse_enter(void) { size_t id = read_uint(); FunctionSig *sig = lookup(functions, id); - if (!sig) { - sig = new FunctionSig; - sig->id = id; - sig->name = read_string(); - sig->num_args = read_uint(); - const char **arg_names = new const char *[sig->num_args]; - for (unsigned i = 0; i < sig->num_args; ++i) { - arg_names[i] = read_string(); + const File::Offset offset = file->currentOffset(); + bool callWithSig = callWithSignature(offset); + if (!sig || callWithSig) { + if (!sig) { + sig = new FunctionSig; + sig->id = id; + sig->name = read_string(); + sig->num_args = read_uint(); + const char **arg_names = new const char *[sig->num_args]; + for (unsigned i = 0; i < sig->num_args; ++i) { + arg_names[i] = read_string(); + } + sig->arg_names = arg_names; + functions[id] = sig; + m_callSigOffsets.insert(offset); + } else { + /* skip over the signature */ + read_string(); /* name */ + int num_args = read_uint(); + for (unsigned i = 0; i < num_args; ++i) { + read_string(); /*arg_name*/ + } } - sig->arg_names = arg_names; - functions[id] = sig; } assert(sig); Call *call = new Call(sig); - call->no = next_call_no++; + + if (hasCallBeenParsed(offset)) { + call->no = callNumForOffset(offset); + } else { + call->no = next_call_no++; + m_callNumOffsets.insert( + std::pair(offset, call->no)); + } if (parse_call_details(call)) { calls.push_back(call); @@ -322,14 +341,23 @@ Value *Parser::parse_string() { Value *Parser::parse_enum() { size_t id = read_uint(); EnumSig *sig = lookup(enums, id); - if (!sig) { - sig = new EnumSig; - sig->id = id; - sig->name = read_string(); - Value *value = parse_value(); - sig->value = value->toSInt(); - delete value; - enums[id] = sig; + const File::Offset offset = file->currentOffset(); + bool enumWithSig = enumWithSignature(offset); + if (!sig || enumWithSig) { + if (!sig) { + sig = new EnumSig; + sig->id = id; + sig->name = read_string(); + Value *value = parse_value(); + sig->value = value->toSInt(); + delete value; + enums[id] = sig; + m_enumSigOffsets.insert(offset); + } else { + read_string(); /*name*/ + Value *value = parse_value(); + delete value; + } } assert(sig); return new Enum(sig); @@ -339,20 +367,31 @@ Value *Parser::parse_enum() { Value *Parser::parse_bitmask() { size_t id = read_uint(); BitmaskSig *sig = lookup(bitmasks, id); - if (!sig) { - sig = new BitmaskSig; - sig->id = id; - sig->num_flags = read_uint(); - BitmaskFlag *flags = new BitmaskFlag[sig->num_flags]; - for (BitmaskFlag *it = flags; it != flags + sig->num_flags; ++it) { - it->name = read_string(); - it->value = read_uint(); - if (it->value == 0 && it != flags) { - std::cerr << "warning: bitmask " << it->name << " is zero but is not first flag\n"; + const File::Offset offset = file->currentOffset(); + bool bitmaskWithSig = bitmaskWithSignature(offset); + if (!sig || bitmaskWithSig) { + if (!sig) { + sig = new BitmaskSig; + sig->id = id; + sig->num_flags = read_uint(); + BitmaskFlag *flags = new BitmaskFlag[sig->num_flags]; + for (BitmaskFlag *it = flags; it != flags + sig->num_flags; ++it) { + it->name = read_string(); + it->value = read_uint(); + if (it->value == 0 && it != flags) { + std::cerr << "warning: bitmask " << it->name << " is zero but is not first flag\n"; + } + } + sig->flags = flags; + bitmasks[id] = sig; + m_bitmaskSigOffsets.insert(offset); + } else { + int num_flags = read_uint(); + for (int i = 0; i < num_flags; ++i) { + read_string(); /*name */ + read_uint(); /* value */ } } - sig->flags = flags; - bitmasks[id] = sig; } assert(sig); @@ -386,17 +425,28 @@ Value *Parser::parse_struct() { size_t id = read_uint(); StructSig *sig = lookup(structs, id); - if (!sig) { - sig = new StructSig; - sig->id = id; - sig->name = read_string(); - sig->num_members = read_uint(); - const char **member_names = new const char *[sig->num_members]; - for (unsigned i = 0; i < sig->num_members; ++i) { - member_names[i] = read_string(); + const File::Offset offset = file->currentOffset(); + bool structWithSig = structWithSignature(offset); + if (!sig || structWithSig) { + if (!sig) { + sig = new StructSig; + sig->id = id; + sig->name = read_string(); + sig->num_members = read_uint(); + const char **member_names = new const char *[sig->num_members]; + for (unsigned i = 0; i < sig->num_members; ++i) { + member_names[i] = read_string(); + } + sig->member_names = member_names; + structs[id] = sig; + m_structSigOffsets.insert(offset); + } else { + read_string(); /* name */ + unsigned num_members = read_uint(); + for (unsigned i = 0; i < num_members; ++i) { + read_string(); /* member_name */ + } } - sig->member_names = member_names; - structs[id] = sig; } assert(sig); @@ -462,4 +512,36 @@ inline int Parser::read_byte(void) { } +inline bool Parser::callWithSignature(const File::Offset &offset) const +{ + return m_callSigOffsets.find(offset) != m_callSigOffsets.end(); +} + +inline bool Parser::structWithSignature(const File::Offset &offset) const +{ + return m_structSigOffsets.find(offset) != m_structSigOffsets.end(); +} + +inline bool Parser::enumWithSignature(const File::Offset &offset) const +{ + return m_enumSigOffsets.find(offset) != m_enumSigOffsets.end(); +} + +inline bool Parser::bitmaskWithSignature(const File::Offset &offset) const +{ + return m_bitmaskSigOffsets.find(offset) != m_bitmaskSigOffsets.end(); +} + +bool Parser::hasCallBeenParsed(const File::Offset &offset) const +{ + return m_callNumOffsets.find(offset) != m_callNumOffsets.end(); +} + +unsigned Parser::callNumForOffset(const File::Offset &offset) const +{ + CallNumOffsets::const_iterator itr = m_callNumOffsets.find(offset); + assert(itr != m_callNumOffsets.end()); + return itr->second; +} + } /* namespace Trace */ diff --git a/trace_parser.hpp b/trace_parser.hpp index a000986..a9f11f7 100644 --- a/trace_parser.hpp +++ b/trace_parser.hpp @@ -29,6 +29,7 @@ #include #include +#include #include "trace_file.hpp" #include "trace_format.hpp" @@ -57,6 +58,15 @@ protected: typedef std::vector BitmaskMap; BitmaskMap bitmasks; + typedef std::set TraceOffsets; + TraceOffsets m_callSigOffsets; + TraceOffsets m_structSigOffsets; + TraceOffsets m_enumSigOffsets; + TraceOffsets m_bitmaskSigOffsets; + + typedef std::map CallNumOffsets; + CallNumOffsets m_callNumOffsets; + unsigned next_call_no; public: @@ -87,6 +97,13 @@ public: file->setCurrentOffset(offset); } + bool callWithSignature(const File::Offset &offset) const; + bool structWithSignature(const File::Offset &offset) const; + bool enumWithSignature(const File::Offset &offset) const; + bool bitmaskWithSignature(const File::Offset &offset) const; + bool hasCallBeenParsed(const File::Offset &offset) const; + unsigned callNumForOffset(const File::Offset &offset) const; + protected: void parse_enter(void);