summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZack Rusin <zack@kde.org>2011-09-01 01:50:56 -0400
committerZack Rusin <zack@kde.org>2011-09-01 01:50:56 -0400
commite0df952b67f3ae38aeb0fd7e32942f8fa53ac49f (patch)
treec004c648ebde59b139b15a7b76bcf54ab72160fb
parent8216d8efc428dd336957433d743af5c4ac2d0d05 (diff)
First working implementation of on-demand-loading of frames/calls.
-rw-r--r--loadertest.cpp2
-rw-r--r--trace_file.hpp34
-rw-r--r--trace_loader.cpp13
-rw-r--r--trace_parser.cpp164
-rw-r--r--trace_parser.hpp17
5 files changed, 185 insertions, 45 deletions
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<Trace::Call*> frame = loader.frame(
- 0);
+ loader.numberOfFrames()/2);
std::vector<Trace::Call*>::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: " <<filename<< " doesn't support seeking "
+ << "\n";
+ return false;
+ }
Trace::Call *call;
File::Offset startOffset;
@@ -102,7 +107,7 @@ bool Loader::isCallAFrameMarker(const Trace::Call *call) const
return false;
}
-std::vector<Trace::Call *> Trace::Loader::frame(int idx)
+std::vector<Trace::Call *> Loader::frame(int idx)
{
int numOfCalls = numberOfCallsInFrame(idx);
if (numOfCalls) {
@@ -113,13 +118,15 @@ std::vector<Trace::Call *> 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<Trace::Call*>();
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<File::Offset, unsigned>(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 <iostream>
#include <list>
+#include <set>
#include "trace_file.hpp"
#include "trace_format.hpp"
@@ -57,6 +58,15 @@ protected:
typedef std::vector<BitmaskSig *> BitmaskMap;
BitmaskMap bitmasks;
+ typedef std::set<File::Offset> TraceOffsets;
+ TraceOffsets m_callSigOffsets;
+ TraceOffsets m_structSigOffsets;
+ TraceOffsets m_enumSigOffsets;
+ TraceOffsets m_bitmaskSigOffsets;
+
+ typedef std::map<File::Offset, unsigned> 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);