1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* //device/tools/dmtracedump/TraceDump.c
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project**
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project** Copyright 2006, The Android Open Source Project
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project**
5de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro** Licensed under the Apache License, Version 2.0 (the "License");
6de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro** you may not use this file except in compliance with the License.
7de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro** You may obtain a copy of the License at
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project**
9de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro**     http://www.apache.org/licenses/LICENSE-2.0
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project**
11de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro** Unless required by applicable law or agreed to in writing, software
12de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro** distributed under the License is distributed on an "AS IS" BASIS,
13de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro** See the License for the specific language governing permissions and
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project** limitations under the License.
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/
175b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Process dmtrace output.
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is the wrong way to go about it -- C is a clumsy language for
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * shuffling data around.  It'll do for a first pass.
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define NOT_VM
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Profile.h"        // from VM header
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdio.h>
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <string.h>
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <unistd.h>
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <inttypes.h>
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <time.h>
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h>
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <assert.h>
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Version number in the key file.  Version 1 uses one byte for the thread id.
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Version 2 uses two bytes for the thread ids.
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint versionNumber;
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* arbitrarily limit indentation */
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define MAX_STACK_DEPTH 10000
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* thread list in key file is not reliable, so just max out */
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define MAX_THREADS     32768
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Size of temporary buffers for escaping html strings */
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define HTML_BUFSIZE 10240
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
506978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince/* Size of methodId->method cache */
516978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince#define METHOD_CACHE_SIZE 2048
5244828ed25841ea5180346695dfc07ef33b2b7e73Jack Veenstra#define METHOD_CACHE_SIZE_MASK (METHOD_CACHE_SIZE - 1)
536978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
546978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince/* Some filter constants */
556978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince#define FILTER_TAG '*'
566978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince#define FILTER_FLAG_THREAD '+'
576978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince#define FILTER_TYPE_CLASS 0
586978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince#define FILTER_TYPE_METHOD 1
596978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
606978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince#define DEFAULT_ACTIVE_THREADS 8
616978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
62de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapirochar *htmlHeader =
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"<html>\n<head>\n<script type=\"text/javascript\" src=\"%ssortable.js\"></script>\n"
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"<script langugage=\"javascript\">\n"
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"function toggle(item) {\n"
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"    obj=document.getElementById(item);\n"
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"    visible=(obj.style.display!=\"none\" && obj.style.display!=\"\");\n"
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"    key=document.getElementById(\"x\" + item);\n"
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"    if (visible) {\n"
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"        obj.style.display=\"none\";\n"
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"        key.innerHTML=\"+\";\n"
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"    } else {\n"
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"        obj.style.display=\"block\";\n"
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"        key.innerHTML=\"-\";\n"
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"    }\n"
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"}\n"
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"function onMouseOver(obj) {\n"
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"    obj.style.background=\"lightblue\";\n"
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"}\n"
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"function onMouseOut(obj) {\n"
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"    obj.style.background=\"white\";\n"
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"}\n"
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"</script>\n"
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"<style type=\"text/css\">\n"
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"div { font-family: courier; font-size: 13 }\n"
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"div.parent { margin-left: 15; display: none }\n"
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"div.leaf { margin-left: 10 }\n"
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"div.header { margin-left: 10 }\n"
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"div.link { margin-left: 10; cursor: move }\n"
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"span.parent { padding-right: 10; }\n"
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"span.leaf { padding-right: 10; }\n"
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"a img { border: 0;}\n"
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"table.sortable th { border-width: 0px 1px 1px 1px; background-color: #ccc;}\n"
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"a { text-decoration: none; }\n"
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"a:hover { text-decoration: underline; }\n"
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"table.sortable th, table.sortable td { text-align: left;}"
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"table.sortable tr.odd td { background-color: #ddd; }\n"
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"table.sortable tr.even td { background-color: #fff; }\n"
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"</style>\n"
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"</head><body>\n\n";
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchar *htmlFooter = "\n</body>\n</html>\n";
103de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapirochar *profileSeparator =
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "======================================================================";
105de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
106de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiroconst char* tableHeader =
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<table class='sortable' id='%s'><tr>\n"
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th>Method</th>\n"
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th>Run 1 (us)</th>\n"
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th>Run 2 (us)</th>\n"
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th>Diff (us)</th>\n"
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th>Diff (%%)</th>\n"
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th>1: # calls</th>\n"
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th>2: # calls</th>\n"
115de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro    "</tr>\n";
116de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
117de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiroconst char* tableHeaderMissing =
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<table class='sortable' id='%s'>\n"
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th>Method</th>\n"
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th>Exclusive</th>\n"
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th>Inclusive</th>\n"
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th># calls</th>\n";
123de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
124de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro#define GRAPH_LABEL_VISITED 0x0001
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define GRAPH_NODE_VISITED  0x0002
126de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Values from the header of the data file.
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct DataHeader {
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned int magic;
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    short version;
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    short offsetToData;
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    long long startWhen;
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} DataHeader;
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Entry from the thread list.
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct ThreadEntry {
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int         threadId;
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* threadName;
1435b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    uint64_t    elapsedTime;
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} ThreadEntry;
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstruct MethodEntry;
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct TimedMethod {
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct TimedMethod *next;
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t elapsedInclusive;
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numCalls;
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct MethodEntry *method;
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} TimedMethod;
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct ClassEntry {
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char *className;
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t elapsedExclusive;
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numMethods;
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct MethodEntry **methods;       /* list of methods in this class */
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numCalls[2];                    /* 0=normal, 1=recursive */
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} ClassEntry;
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct UniqueMethodEntry {
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t elapsedExclusive;
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numMethods;
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct MethodEntry **methods;       /* list of methods with same name */
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numCalls[2];                    /* 0=normal, 1=recursive */
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} UniqueMethodEntry;
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Entry from the method list.
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct MethodEntry {
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned int methodId;
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* className;
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* methodName;
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* signature;
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* fileName;
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int lineNum;
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t elapsedExclusive;
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t elapsedInclusive;
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t topExclusive;              /* non-recursive exclusive time */
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t recursiveInclusive;
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct TimedMethod *parents[2];     /* 0=normal, 1=recursive */
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct TimedMethod *children[2];    /* 0=normal, 1=recursive */
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numCalls[2];                    /* 0=normal, 1=recursive */
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int index;                  /* used after sorting to number methods */
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int recursiveEntries;       /* number of entries on the stack */
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int graphState;             /* used when graphing to see if this method has been visited before */
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} MethodEntry;
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The parsed contents of the key file.
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct DataKeys {
1955b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    char*        fileData;      /* contents of the entire file */
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    long         fileLen;
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int          numThreads;
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ThreadEntry* threads;
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int          numMethods;
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry* methods;       /* 2 extra methods: "toplevel" and "unknown" */
2016978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int*         methodCache;   /* methodId->methodIndex mapping */
2026978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    // TODO change to map methodId->method itself
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} DataKeys;
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define TOPLEVEL_INDEX 0
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define UNKNOWN_INDEX 1
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct StackEntry {
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry *method;
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t    entryTime;
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} StackEntry;
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct CallStack {
2146978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int           top;
2156978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    StackEntry    calls[MAX_STACK_DEPTH];
2166978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    uint64_t      lastEventTime;
2176978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    uint64_t      threadStartTime;
2186978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    uint64_t*     remTimes;
2196978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    // Note: remTimes keeps a sum of 'un-allocated' time for each thread, in case
2206978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    // we need to allocate it to one (or many) filter later. This would happen when
2216978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    // we see a method exit that maches a filter, but whose entry we hadn't seen.
2226978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    // TODO: consider moving remTimes into FilterTimes and change logic appropriately
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} CallStack;
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct DiffEntry {
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry* method1;
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry* method2;
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int64_t differenceExclusive;
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int64_t differenceInclusive;
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    double differenceExclusivePercentage;
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    double differenceInclusivePercentage;
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} DiffEntry;
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// Global options
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct Options {
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* traceFileName;
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* diffFileName;
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* graphFileName;
2396978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    const char* filterFileName;
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int keepDotFile;
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int dump;
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int outputHtml;
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* sortableUrl;
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int threshold;
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} Options;
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct TraceData {
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numClasses;
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassEntry *classes;
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStack *stacks[MAX_THREADS];
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int depth[MAX_THREADS];
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numUniqueMethods;
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UniqueMethodEntry *uniqueMethods;
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} TraceData;
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2566978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipincetypedef struct FilterKey {
2576978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int       type[2];    /* 0=class, 1=method; 2 needed for start and end keys */
2586978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    uint32_t  flags;      /* 1st bit = include cross-thread time */
2596978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    char*     keys[2];    /* 2 needed for start and end keys */
2606978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince} FilterKey;
2616978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
2626978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipincetypedef struct FilterTimes {
2636978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    uint64_t   totalWaitTime;
2646978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    uint64_t*  threadWaitTimes;
2656978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    uint64_t*  threadExecutionTimesWhileWaiting;
2666978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    uint64_t*  threadExecutionTimes;
2676978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince} FilterTimes;
2686978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
2696978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipincetypedef struct Filter {
2706978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    char*       filterName;
2716978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    FilterKey*  filterKeys;
2726978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int         numKeys;
2736978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int         activeCount;
2746978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int*        activeThreads;
2756978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int*        activationKeys;
2766978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    FilterTimes times;
2776978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince} Filter;
2786978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
2796978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipinceint numFilters = 0; // global
2806978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic Options gOptions;
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Escapes characters in the source string that are html special entities.
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The escaped string is written to "dest" which must be large enough to
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * hold the result.  A pointer to "dest" is returned.  The characters and
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * their corresponding escape sequences are:
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  '<'  &lt;
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  '>'  &gt;
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  '&'  &amp;
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchar *htmlEscape(const char *src, char *dest, int len)
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char *destStart = dest;
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (src == NULL)
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int nbytes = 0;
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (*src) {
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*src == '<') {
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            nbytes += 4;
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (nbytes >= len)
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = '&';
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = 'l';
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = 't';
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = ';';
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (*src == '>') {
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            nbytes += 4;
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (nbytes >= len)
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = '&';
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = 'g';
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = 't';
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = ';';
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (*src == '&') {
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            nbytes += 5;
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (nbytes >= len)
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = '&';
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = 'a';
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = 'm';
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = 'p';
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = ';';
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            nbytes += 1;
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (nbytes >= len)
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = *src;
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        src += 1;
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (nbytes >= len) {
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr, "htmlEscape(): buffer overflow\n");
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        exit(1);
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *dest = 0;
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return destStart;
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Initializes a MethodEntry
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid initMethodEntry(MethodEntry *method, unsigned int methodId,
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     const char *className, const char *methodName,
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     const char *signature, const char* fileName,
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     const char* lineNumStr)
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->methodId = methodId;
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->className = className;
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->methodName = methodName;
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->signature = signature;
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->fileName = fileName;
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->lineNum = (lineNumStr != NULL) ? atoi(lineNumStr) : -1;
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->elapsedExclusive = 0;
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->elapsedInclusive = 0;
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->topExclusive = 0;
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->recursiveInclusive = 0;
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->parents[0] = NULL;
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->parents[1] = NULL;
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->children[0] = NULL;
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->children[1] = NULL;
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->numCalls[0] = 0;
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->numCalls[1] = 0;
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->index = 0;
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->recursiveEntries = 0;
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This comparison function is called from qsort() to sort
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * methods into decreasing order of exclusive elapsed time.
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint compareElapsedExclusive(const void *a, const void *b) {
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t elapsed1, elapsed2;
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const MethodEntry *methodA = *(const MethodEntry**)a;
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const MethodEntry *methodB = *(const MethodEntry**)b;
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elapsed1 = methodA->elapsedExclusive;
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elapsed2 = methodB->elapsedExclusive;
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elapsed1 < elapsed2)
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elapsed1 > elapsed2)
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the elapsed times of two methods are equal, then sort them
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * into alphabetical order.
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = strcmp(methodA->className, methodB->className);
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result == 0) {
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodA->methodName == NULL || methodB->methodName == NULL) {
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            unsigned int idA = methodA->methodId;
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            unsigned int idB = methodB->methodId;
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (idA < idB)
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return -1;
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (idA > idB)
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return 1;
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 0;
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = strcmp(methodA->methodName, methodB->methodName);
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result == 0)
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result = strcmp(methodA->signature, methodB->signature);
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This comparison function is called from qsort() to sort
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * methods into decreasing order of inclusive elapsed time.
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint compareElapsedInclusive(const void *a, const void *b) {
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const MethodEntry *methodA, *methodB;
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t elapsed1, elapsed2;
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    methodA = *(MethodEntry const **)a;
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    methodB = *(MethodEntry const **)b;
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elapsed1 = methodA->elapsedInclusive;
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elapsed2 = methodB->elapsedInclusive;
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elapsed1 < elapsed2)
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elapsed1 > elapsed2)
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the elapsed times of two methods are equal, then sort them
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * into alphabetical order.
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = strcmp(methodA->className, methodB->className);
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result == 0) {
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodA->methodName == NULL || methodB->methodName == NULL) {
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            unsigned int idA = methodA->methodId;
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            unsigned int idB = methodB->methodId;
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (idA < idB)
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return -1;
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (idA > idB)
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return 1;
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 0;
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = strcmp(methodA->methodName, methodB->methodName);
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result == 0)
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result = strcmp(methodA->signature, methodB->signature);
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This comparison function is called from qsort() to sort
4485b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince * threads into decreasing order of elapsed time.
4495b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince */
4505b55af706cf3823494123da092a0a0319297a93eRodrigo Ipinceint compareElapsed(const void *a, const void *b) {
4515b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    const ThreadEntry *threadA, *threadB;
4525b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    uint64_t elapsed1, elapsed2;
4535b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    int result = 0;
4545b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
4555b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    threadA = (ThreadEntry const *)a;
4565b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    threadB = (ThreadEntry const *)b;
4575b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    elapsed1 = threadA->elapsedTime;
4585b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    elapsed2 = threadB->elapsedTime;
4595b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    if (elapsed1 < elapsed2)
4605b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        return 1;
4615b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    if (elapsed1 > elapsed2)
4625b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        return -1;
4635b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
4645b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    /* If the elapsed times of two threads are equal, then sort them
4655b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince     * by thread id.
4665b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince     */
4675b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    int idA = threadA->threadId;
4685b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    int idB = threadB->threadId;
4695b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    if (idA < idB)
4705b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        result = -1;
4715b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    if (idA > idB)
4725b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        result = 1;
4735b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
4745b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    return result;
4755b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince}
4765b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
4775b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince/*
4785b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince * This comparison function is called from qsort() to sort
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TimedMethods into decreasing order of inclusive elapsed time.
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint compareTimedMethod(const void *a, const void *b) {
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const TimedMethod *timedA, *timedB;
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t elapsed1, elapsed2;
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    timedA = (TimedMethod const *)a;
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    timedB = (TimedMethod const *)b;
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elapsed1 = timedA->elapsedInclusive;
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elapsed2 = timedB->elapsedInclusive;
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elapsed1 < elapsed2)
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elapsed1 > elapsed2)
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the elapsed times of two methods are equal, then sort them
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * into alphabetical order.
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry *methodA = timedA->method;
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry *methodB = timedB->method;
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = strcmp(methodA->className, methodB->className);
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result == 0) {
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodA->methodName == NULL || methodB->methodName == NULL) {
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            unsigned int idA = methodA->methodId;
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            unsigned int idB = methodB->methodId;
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (idA < idB)
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return -1;
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (idA > idB)
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return 1;
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 0;
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = strcmp(methodA->methodName, methodB->methodName);
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result == 0)
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result = strcmp(methodA->signature, methodB->signature);
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This comparison function is called from qsort() to sort
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * MethodEntry pointers into alphabetical order of class names.
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint compareClassNames(const void *a, const void *b) {
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const MethodEntry *methodA = *(const MethodEntry**)a;
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const MethodEntry *methodB = *(const MethodEntry**)b;
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = strcmp(methodA->className, methodB->className);
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result == 0) {
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int idA = methodA->methodId;
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int idB = methodB->methodId;
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (idA < idB)
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (idA > idB)
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 1;
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 0;
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This comparison function is called from qsort() to sort
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * classes into decreasing order of exclusive elapsed time.
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint compareClassExclusive(const void *a, const void *b) {
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t elapsed1, elapsed2;
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassEntry *classA = *(const ClassEntry**)a;
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassEntry *classB = *(const ClassEntry**)b;
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elapsed1 = classA->elapsedExclusive;
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elapsed2 = classB->elapsedExclusive;
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elapsed1 < elapsed2)
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elapsed1 > elapsed2)
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the elapsed times of two classs are equal, then sort them
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * into alphabetical order.
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = strcmp(classA->className, classB->className);
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result == 0) {
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Break ties with the first method id.  This is probably not
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * needed.
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int idA = classA->methods[0]->methodId;
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int idB = classB->methods[0]->methodId;
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (idA < idB)
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (idA > idB)
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 1;
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 0;
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This comparison function is called from qsort() to sort
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * MethodEntry pointers into alphabetical order by method name,
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * then by class name.
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint compareMethodNames(const void *a, const void *b) {
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const MethodEntry *methodA = *(const MethodEntry**)a;
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const MethodEntry *methodB = *(const MethodEntry**)b;
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (methodA->methodName == NULL || methodB->methodName == NULL) {
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return compareClassNames(a, b);
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = strcmp(methodA->methodName, methodB->methodName);
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result == 0) {
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = strcmp(methodA->className, methodB->className);
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result == 0) {
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            unsigned int idA = methodA->methodId;
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            unsigned int idB = methodB->methodId;
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (idA < idB)
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return -1;
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (idA > idB)
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return 1;
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 0;
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This comparison function is called from qsort() to sort
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * unique methods into decreasing order of exclusive elapsed time.
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint compareUniqueExclusive(const void *a, const void *b) {
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t elapsed1, elapsed2;
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const UniqueMethodEntry *uniqueA = *(const UniqueMethodEntry**)a;
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const UniqueMethodEntry *uniqueB = *(const UniqueMethodEntry**)b;
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elapsed1 = uniqueA->elapsedExclusive;
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elapsed2 = uniqueB->elapsedExclusive;
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elapsed1 < elapsed2)
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elapsed1 > elapsed2)
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the elapsed times of two methods are equal, then sort them
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * into alphabetical order.
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = strcmp(uniqueA->methods[0]->className,
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    uniqueB->methods[0]->className);
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result == 0) {
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int idA = uniqueA->methods[0]->methodId;
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int idB = uniqueB->methods[0]->methodId;
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (idA < idB)
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (idA > idB)
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 1;
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 0;
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free a DataKeys struct.
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid freeDataKeys(DataKeys* pKeys)
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pKeys == NULL)
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(pKeys->fileData);
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(pKeys->threads);
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(pKeys->methods);
6506978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    free(pKeys->methodCache);
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(pKeys);
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the offset to the next occurrence of the specified character.
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "data" should point somewhere within the current line.  "len" is the
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * number of bytes left in the buffer.
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns -1 if we hit the end of the buffer.
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint findNextChar(const char* data, int len, char lookFor)
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* start = data;
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (len > 0) {
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*data == lookFor)
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return data - start;
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        data++;
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        len--;
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return -1;
675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6776978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipinceint countLinesToChar(const char* data, int len, const char toFind)
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int count = 0;
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int next;
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6826978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    while (*data != toFind) {
683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        next = findNextChar(data, len, '\n');
684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (next < 0)
6856978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    return count;
686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        count++;
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        data += next+1;
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        len -= next+1;
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return count;
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
6956978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * Count the number of lines until the next token.
6966978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince *
6976978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * Returns 0 if none found before EOF.
6986978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince */
6996978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipinceint countLinesToToken(const char* data, int len)
7006978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince{
7016978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    return countLinesToChar(data, len, TOKEN_CHAR);
7026978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince}
7036978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
7046978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince/*
705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Make sure we're at the start of the right section.
706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the length of the token line, or -1 if something is wrong.
708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint checkToken(const char* data, int len, const char* cmpStr)
710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int cmpLen = strlen(cmpStr);
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int next;
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*data != TOKEN_CHAR) {
715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr,
716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "ERROR: not at start of %s (found '%.10s')\n", cmpStr, data);
717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    next = findNextChar(data, len, '\n');
721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (next < cmpLen+1)
722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (strncmp(data+1, cmpStr, cmpLen) != 0) {
725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr, "ERROR: '%s' not found (got '%.7s')\n", cmpStr, data+1);
726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return next+1;
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parse the "*version" section.
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectlong parseVersion(DataKeys* pKeys, long offset, int verbose)
736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* data;
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* dataEnd;
739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, count, next;
740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (offset < 0)
742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data = pKeys->fileData + offset;
745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dataEnd = pKeys->fileData + pKeys->fileLen;
746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    next = checkToken(data, dataEnd - data, "version");
747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (next <= 0)
748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data += next;
751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Count the number of items in the "version" section.
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    count = countLinesToToken(data, dataEnd - data);
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (count <= 0) {
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr,
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "ERROR: failed while reading version (found %d)\n", count);
759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* find the end of the line */
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    next = findNextChar(data, dataEnd - data, '\n');
764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (next < 0)
765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data[next] = '\0';
768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    versionNumber = strtoul(data, NULL, 0);
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (verbose)
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("VERSION: %d\n", versionNumber);
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data += next+1;
773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* skip over the rest of the stuff, which is "name=value" lines */
775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 1; i < count; i++) {
776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        next = findNextChar(data, dataEnd - data, '\n');
777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (next < 0)
778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //data[next] = '\0';
780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //printf("IGNORING: '%s'\n", data);
781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        data += next+1;
782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return data - pKeys->fileData;
785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parse the "*threads" section.
789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectlong parseThreads(DataKeys* pKeys, long offset)
791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* data;
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* dataEnd;
794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, next, tab, count;
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (offset < 0)
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data = pKeys->fileData + offset;
800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dataEnd = pKeys->fileData + pKeys->fileLen;
801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    next = checkToken(data, dataEnd - data, "threads");
802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data += next;
804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Count the number of thread entries (one per line).
807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    count = countLinesToToken(data, dataEnd - data);
809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (count <= 0) {
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr,
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "ERROR: failed while reading threads (found %d)\n", count);
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //printf("+++ found %d threads\n", count);
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pKeys->threads = (ThreadEntry*) malloc(sizeof(ThreadEntry) * count);
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pKeys->threads == NULL)
818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Extract all entries.
822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < count; i++) {
824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        next = findNextChar(data, dataEnd - data, '\n');
825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(next > 0);
826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        data[next] = '\0';
827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tab = findNextChar(data, next, '\t');
829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        data[tab] = '\0';
830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pKeys->threads[i].threadId = atoi(data);
832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pKeys->threads[i].threadName = data + tab +1;
833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        data += next+1;
835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pKeys->numThreads = count;
838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return data - pKeys->fileData;
839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parse the "*methods" section.
843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectlong parseMethods(DataKeys* pKeys, long offset)
845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* data;
847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* dataEnd;
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, next, count;
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (offset < 0)
851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data = pKeys->fileData + offset;
854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dataEnd = pKeys->fileData + pKeys->fileLen;
855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    next = checkToken(data, dataEnd - data, "methods");
856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (next < 0)
857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data += next;
860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Count the number of method entries (one per line).
863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    count = countLinesToToken(data, dataEnd - data);
865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (count <= 0) {
866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr,
867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "ERROR: failed while reading methods (found %d)\n", count);
868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Reserve an extra method at location 0 for the "toplevel" method,
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and another extra method for all other "unknown" methods.
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    count += 2;
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pKeys->methods = (MethodEntry*) malloc(sizeof(MethodEntry) * count);
876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pKeys->methods == NULL)
877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    initMethodEntry(&pKeys->methods[TOPLEVEL_INDEX], 0, "(toplevel)",
879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        NULL, NULL, NULL, NULL);
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    initMethodEntry(&pKeys->methods[UNKNOWN_INDEX], 0, "(unknown)",
881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        NULL, NULL, NULL, NULL);
882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Extract all entries, starting with index 2.
885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = UNKNOWN_INDEX + 1; i < count; i++) {
887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int tab1, tab2, tab3, tab4, tab5;
888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int id;
889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* endptr;
890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        next = findNextChar(data, dataEnd - data, '\n');
892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(next > 0);
893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        data[next] = '\0';
894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tab1 = findNextChar(data, next, '\t');
896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tab2 = findNextChar(data+(tab1+1), next-(tab1+1), '\t');
897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tab3 = findNextChar(data+(tab1+tab2+2), next-(tab1+tab2+2), '\t');
898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tab4 = findNextChar(data+(tab1+tab2+tab3+3),
899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            next-(tab1+tab2+tab3+3), '\t');
900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tab5 = findNextChar(data+(tab1+tab2+tab3+tab4+4),
901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            next-(tab1+tab2+tab3+tab4+4), '\t');
902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (tab1 < 0) {
903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fprintf(stderr, "ERROR: missing field on method line: '%s'\n",
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    data);
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(data[tab1] == '\t');
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        data[tab1] = '\0';
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        id = strtoul(data, &endptr, 0);
911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*endptr != '\0') {
912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fprintf(stderr, "ERROR: bad method ID '%s'\n", data);
913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Allow files that specify just a function name, instead of requiring
917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // "class \t method \t signature"
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (tab2 > 0 && tab3 > 0) {
919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tab2 += tab1+1;
920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tab3 += tab2+1;
921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(data[tab2] == '\t');
922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(data[tab3] == '\t');
923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            data[tab2] = data[tab3] = '\0';
924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // This is starting to get awkward.  Allow filename and line #.
926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (tab4 > 0 && tab5 > 0) {
927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                tab4 += tab3+1;
928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                tab5 += tab4+1;
929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(data[tab4] == '\t');
931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(data[tab5] == '\t');
932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                data[tab4] = data[tab5] = '\0';
933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                initMethodEntry(&pKeys->methods[i], id, data + tab1 +1,
935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        data + tab2 +1, data + tab3 +1, data + tab4 +1,
936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        data + tab5 +1);
937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                initMethodEntry(&pKeys->methods[i], id, data + tab1 +1,
939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        data + tab2 +1, data + tab3 +1, NULL, NULL);
940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            initMethodEntry(&pKeys->methods[i], id, data + tab1 +1,
943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                NULL, NULL, NULL, NULL);
944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        data += next+1;
947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pKeys->numMethods = count;
950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return data - pKeys->fileData;
951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parse the "*end" section.
955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectlong parseEnd(DataKeys* pKeys, long offset)
957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* data;
959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* dataEnd;
960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int next;
961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (offset < 0)
963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data = pKeys->fileData + offset;
966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dataEnd = pKeys->fileData + pKeys->fileLen;
967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    next = checkToken(data, dataEnd - data, "end");
968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (next < 0)
969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data += next;
972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return data - pKeys->fileData;
974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sort the thread list entries.
978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int compareThreads(const void* thread1, const void* thread2)
980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return ((const ThreadEntry*) thread1)->threadId -
982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ((const ThreadEntry*) thread2)->threadId;
983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid sortThreadList(DataKeys* pKeys)
986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(pKeys->threads, pKeys->numThreads, sizeof(pKeys->threads[0]),
988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        compareThreads);
989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sort the method list entries.
993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int compareMethods(const void* meth1, const void* meth2)
995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned int id1, id2;
997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    id1 = ((const MethodEntry*) meth1)->methodId;
999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    id2 = ((const MethodEntry*) meth2)->methodId;
1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (id1 < id2)
1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (id1 > id2)
1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid sortMethodList(DataKeys* pKeys)
1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(pKeys->methods, pKeys->numMethods, sizeof(MethodEntry),
1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        compareMethods);
1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parse the key section, and return a copy of the parsed contents.
1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectDataKeys* parseKeys(FILE *fp, int verbose)
1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DataKeys* pKeys = NULL;
1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    long offset;
1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pKeys = (DataKeys*) calloc(1, sizeof(DataKeys));
1023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pKeys == NULL)
1024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto fail;
1025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We load the entire file into memory.  We do this, rather than memory-
1028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * mapping it, because we want to change some whitespace to NULs.
1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (fseek(fp, 0L, SEEK_END) != 0) {
1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        perror("fseek");
1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto fail;
1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pKeys->fileLen = ftell(fp);
1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pKeys->fileLen == 0) {
1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr, "Key file is empty.\n");
1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto fail;
1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    rewind(fp);
1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pKeys->fileData = (char*) malloc(pKeys->fileLen);
1042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pKeys->fileData == NULL) {
1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr, "ERROR: unable to alloc %ld bytes\n", pKeys->fileLen);
1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto fail;
1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (fread(pKeys->fileData, 1, pKeys->fileLen, fp) != (size_t) pKeys->fileLen)
1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
1049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr, "ERROR: unable to read %ld bytes from trace file\n",
1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pKeys->fileLen);
1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto fail;
1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    offset = 0;
1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    offset = parseVersion(pKeys, offset, verbose);
1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    offset = parseThreads(pKeys, offset);
1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    offset = parseMethods(pKeys, offset);
1059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    offset = parseEnd(pKeys, offset);
1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (offset < 0)
1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto fail;
1062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Leave fp pointing to the beginning of the data section. */
1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fseek(fp, offset, SEEK_SET);
1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sortThreadList(pKeys);
1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sortMethodList(pKeys);
1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Dump list of threads.
1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (verbose) {
1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("Threads (%d):\n", pKeys->numThreads);
1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < pKeys->numThreads; i++) {
1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("%2d %s\n",
1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   pKeys->threads[i].threadId, pKeys->threads[i].threadName);
1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
1081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Dump list of methods.
1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (verbose) {
1085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("Methods (%d):\n", pKeys->numMethods);
1086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < pKeys->numMethods; i++) {
1087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("0x%08x %s : %s : %s\n",
10886978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince                   pKeys->methods[i].methodId >> 2, pKeys->methods[i].className,
1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   pKeys->methods[i].methodName, pKeys->methods[i].signature);
1090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return pKeys;
1095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfail:
1097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    freeDataKeys(pKeys);
1098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return NULL;
1099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Read values from the binary data file.
1104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Make the return value "unsigned int" instead of "unsigned short" so that
1107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we can detect EOF.
1108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectunsigned int read2LE(FILE* fp)
1110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned int val;
1112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val = getc(fp);
1114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= getc(fp) << 8;
1115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return val;
1116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectunsigned int read4LE(FILE* fp)
1118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned int val;
1120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val = getc(fp);
1122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= getc(fp) << 8;
1123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= getc(fp) << 16;
1124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= getc(fp) << 24;
1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return val;
1126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectunsigned long long read8LE(FILE* fp)
1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned long long val;
1130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val = getc(fp);
1132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= (unsigned long long) getc(fp) << 8;
1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= (unsigned long long) getc(fp) << 16;
1134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= (unsigned long long) getc(fp) << 24;
1135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= (unsigned long long) getc(fp) << 32;
1136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= (unsigned long long) getc(fp) << 40;
1137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= (unsigned long long) getc(fp) << 48;
1138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= (unsigned long long) getc(fp) << 56;
1139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return val;
1140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parse the header of the data section.
1144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns with the file positioned at the start of the record data.
1146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint parseDataHeader(FILE *fp, DataHeader* pHeader)
1148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pHeader->magic = read4LE(fp);
1150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pHeader->version = read2LE(fp);
1151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pHeader->offsetToData = read2LE(fp);
1152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pHeader->startWhen = read8LE(fp);
1153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (fseek(fp, pHeader->offsetToData - 16, SEEK_CUR) != 0) {
1155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
1156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
1159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
11625b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince * Look up a method by its method ID (using binary search).
1163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns NULL if no matching method was found.
1165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectMethodEntry* lookupMethod(DataKeys* pKeys, unsigned int methodId)
1167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int hi, lo, mid;
1169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned int id;
11706978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int hashedId;
11716978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
11726978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    /* Create cache if it doesn't already exist */
11736978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    if (pKeys->methodCache == NULL) {
1174fe1d6d586614fa51d82857e09128d6671be21d56Andy McFadden        pKeys->methodCache = (int*) calloc(METHOD_CACHE_SIZE, sizeof(int));
11756978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    }
11766978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
117744828ed25841ea5180346695dfc07ef33b2b7e73Jack Veenstra    // ids are multiples of 4, so shift
117844828ed25841ea5180346695dfc07ef33b2b7e73Jack Veenstra    hashedId = (methodId >> 2) & METHOD_CACHE_SIZE_MASK;
11796978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    if (pKeys->methodCache[hashedId]) /* cache hit */
11806978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        if (pKeys->methods[pKeys->methodCache[hashedId]].methodId == methodId)
11816978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    return &pKeys->methods[pKeys->methodCache[hashedId]];
1182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    lo = 0;
1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    hi = pKeys->numMethods - 1;
1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (hi >= lo) {
1187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mid = (hi + lo) / 2;
1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        id = pKeys->methods[mid].methodId;
11906978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        if (id == methodId) {         /* match, put in cache */
119144828ed25841ea5180346695dfc07ef33b2b7e73Jack Veenstra	    hashedId = (methodId >> 2) & METHOD_CACHE_SIZE_MASK;
11926978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    pKeys->methodCache[hashedId] = mid;
11936978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    return &pKeys->methods[mid];
11946978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	} else if (id < methodId)       /* too low */
1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lo = mid + 1;
1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else                          /* too high */
1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hi = mid - 1;
1198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return NULL;
1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Reads the next data record, and assigns the data values to threadId,
1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * methodVal and elapsedTime.  On end-of-file, the threadId, methodVal,
1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and elapsedTime are unchanged.  Returns 1 on end-of-file, otherwise
1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * returns 0.
1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint readDataRecord(FILE *dataFp, int *threadId, unsigned int *methodVal,
1210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   uint64_t *elapsedTime)
1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int id;
1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * TODO:
1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This SHOULD NOT be keyed off of the global version number!  Use
1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a name=value setting in the version area instead!
1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (versionNumber == 1) {
1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        id = getc(dataFp);
1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        id = read2LE(dataFp);
1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (id == EOF)
1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *threadId = id;
1227de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *methodVal = read4LE(dataFp);
1229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *elapsedTime = read4LE(dataFp);
1230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (feof(dataFp)) {
1231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr, "WARNING: hit EOF mid-record\n");
1232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
1233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
1235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Read the key file and use it to produce formatted output from the
1239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * data file.
1240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dumpTrace()
1242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static const char* actionStr[] = { "ent", "xit", "unr", "???" };
1244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry bogusMethod = { 0, "???", "???", "???", "???", -1, 0, 0, 0, 0,
1245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                {NULL, NULL}, {NULL, NULL}, {0, 0}, 0, 0, -1 };
1246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char bogusBuf[80];
1247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char spaces[MAX_STACK_DEPTH+1];
1248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    FILE* dataFp = NULL;
1249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DataHeader dataHeader;
1250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DataKeys* pKeys = NULL;
1251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    TraceData traceData;
1253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //printf("Dumping '%s' '%s'\n", dataFileName, keyFileName);
1255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(spaces, '.', MAX_STACK_DEPTH);
1257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    spaces[MAX_STACK_DEPTH] = '\0';
1258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < MAX_THREADS; i++)
1260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        traceData.depth[i] = 2;       // adjust for return from start function
1261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dataFp = fopen(gOptions.traceFileName, "r");
1263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dataFp == NULL)
1264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((pKeys = parseKeys(dataFp, 1)) == NULL)
1267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (parseDataHeader(dataFp, &dataHeader) < 0)
1270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("Trace (threadID action usecs class.method signature):\n");
1273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (1) {
1275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        MethodEntry* method;
1276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int threadId;
1277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int methodVal;
1278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        uint64_t elapsedTime;
1279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int action, printDepth;
1280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int methodId, lastEnter = 0;
1281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int mismatch = 0;
1282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char depthNote;
1283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Extract values from file.
1286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (readDataRecord(dataFp, &threadId, &methodVal, &elapsedTime))
1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        action = METHOD_ACTION(methodVal);
1291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodId = METHOD_ID(methodVal);
1292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Generate a line of output.
1295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (action == METHOD_TRACE_ENTER) {
1297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            traceData.depth[threadId]++;
1298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lastEnter = methodId;
1299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* quick test for mismatched adjacent enter/exit */
1301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (lastEnter != 0 && lastEnter != methodId)
1302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                mismatch = 1;
1303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printDepth = traceData.depth[threadId];
1306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        depthNote = ' ';
1307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (printDepth < 0) {
1308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printDepth = 0;
1309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            depthNote = '-';
1310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (printDepth > MAX_STACK_DEPTH) {
1311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printDepth = MAX_STACK_DEPTH;
1312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            depthNote = '+';
1313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        method = lookupMethod(pKeys, methodId);
1316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method == NULL) {
1317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method = &bogusMethod;
1318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(bogusBuf, "methodId: 0x%x", methodId);
1319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->signature = bogusBuf;
1320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project	if (method->methodName) {
1323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project	    printf("%2d %s%c %8lld%c%s%s.%s %s\n", threadId,
1324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project		   actionStr[action], mismatch ? '!' : ' ',
1325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project		   elapsedTime, depthNote,
1326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project		   spaces + (MAX_STACK_DEPTH - printDepth),
1327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project		   method->className, method->methodName, method->signature);
1328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project	} else {
1329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project	    printf("%2d %s%c %8lld%c%s%s\n", threadId,
1330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project		   actionStr[action], mismatch ? '!' : ' ',
1331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project		   elapsedTime, depthNote,
1332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project		   spaces + (MAX_STACK_DEPTH - printDepth),
1333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project		   method->className);
1334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project	}
1335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (action != METHOD_TRACE_ENTER) {
1337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            traceData.depth[threadId]--;  /* METHOD_TRACE_EXIT or METHOD_TRACE_UNROLL */
1338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lastEnter = 0;
1339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mismatch = 0;
1342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
1345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dataFp != NULL)
1346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fclose(dataFp);
1347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pKeys != NULL)
1348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        freeDataKeys(pKeys);
1349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* This routine adds the given time to the parent and child methods.
1352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is called when the child routine exits, after the child has
1353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * been popped from the stack.  The elapsedTime parameter is the
1354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * duration of the child routine, including time spent in called routines.
1355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid addInclusiveTime(MethodEntry *parent, MethodEntry *child,
1357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                      uint64_t elapsedTime)
1358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    TimedMethod *pTimed;
1360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
1362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool verbose = false;
1363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (strcmp(child->className, debugClassName) == 0)
1364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        verbose = true;
1365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int childIsRecursive = (child->recursiveEntries > 0);
1368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int parentIsRecursive = (parent->recursiveEntries > 1);
1369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (child->recursiveEntries == 0) {
1371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        child->elapsedInclusive += elapsedTime;
1372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else if (child->recursiveEntries == 1) {
1373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        child->recursiveInclusive += elapsedTime;
1374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    child->numCalls[childIsRecursive] += 1;
1376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
1378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (verbose) {
1379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr,
1380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "%s %d elapsedTime: %lld eI: %lld, rI: %lld\n",
1381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                child->className, child->recursiveEntries,
1382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                elapsedTime, child->elapsedInclusive,
1383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                child->recursiveInclusive);
1384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Find the child method in the parent */
1388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    TimedMethod *children = parent->children[parentIsRecursive];
1389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (pTimed = children; pTimed; pTimed = pTimed->next) {
1390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pTimed->method == child) {
1391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pTimed->elapsedInclusive += elapsedTime;
1392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pTimed->numCalls += 1;
1393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pTimed == NULL) {
1397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Allocate a new TimedMethod */
1398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pTimed = (TimedMethod *) malloc(sizeof(TimedMethod));
1399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pTimed->elapsedInclusive = elapsedTime;
1400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pTimed->numCalls = 1;
1401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pTimed->method = child;
1402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Add it to the front of the list */
1404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pTimed->next = children;
1405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        parent->children[parentIsRecursive] = pTimed;
1406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Find the parent method in the child */
1409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    TimedMethod *parents = child->parents[childIsRecursive];
1410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (pTimed = parents; pTimed; pTimed = pTimed->next) {
1411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pTimed->method == parent) {
1412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pTimed->elapsedInclusive += elapsedTime;
1413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pTimed->numCalls += 1;
1414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pTimed == NULL) {
1418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Allocate a new TimedMethod */
1419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pTimed = (TimedMethod *) malloc(sizeof(TimedMethod));
1420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pTimed->elapsedInclusive = elapsedTime;
1421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pTimed->numCalls = 1;
1422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pTimed->method = parent;
1423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Add it to the front of the list */
1425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pTimed->next = parents;
1426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        child->parents[childIsRecursive] = pTimed;
1427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
1430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (verbose) {
1431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr,
1432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "  %s %d eI: %lld\n",
1433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                parent->className, parent->recursiveEntries,
1434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pTimed->elapsedInclusive);
1435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Sorts a linked list and returns a newly allocated array containing
1440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the sorted entries.
1441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectTimedMethod *sortTimedMethodList(TimedMethod *list, int *num)
1443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii;
1445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    TimedMethod *pTimed, *sorted;
1446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Count the elements */
1448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int num_entries = 0;
1449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (pTimed = list; pTimed; pTimed = pTimed->next)
1450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        num_entries += 1;
1451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *num = num_entries;
1452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (num_entries == 0)
1453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
1454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Copy all the list elements to a new array and sort them */
1456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sorted = (TimedMethod *) malloc(sizeof(TimedMethod) * num_entries);
1457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0, pTimed = list; pTimed; pTimed = pTimed->next, ++ii)
1458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        memcpy(&sorted[ii], pTimed, sizeof(TimedMethod));
1459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(sorted, num_entries, sizeof(TimedMethod), compareTimedMethod);
1460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Fix up the "next" pointers so that they work. */
1462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < num_entries - 1; ++ii)
1463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sorted[ii].next = &sorted[ii + 1];
1464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sorted[num_entries - 1].next = NULL;
1465de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return sorted;
1467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Define flag values for printInclusiveMethod() */
1470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic const int kIsRecursive = 1;
1471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* This prints the inclusive stats for all the parents or children of a
1473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * method, depending on the list that is passed in.
1474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid printInclusiveMethod(MethodEntry *method, TimedMethod *list, int numCalls,
1476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                          int flags)
1477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int num;
1479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    TimedMethod *pTimed;
1480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char buf[80];
1481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char *anchor_close;
1482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char *spaces = "      ";    /* 6 spaces */
1483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int num_spaces = strlen(spaces);
1484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char *space_ptr = &spaces[num_spaces];
1485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char *className, *methodName, *signature;
1486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char classBuf[HTML_BUFSIZE], methodBuf[HTML_BUFSIZE];
1487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char signatureBuf[HTML_BUFSIZE];
1488de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    anchor_close = "";
1490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml)
1491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        anchor_close = "</a>";
1492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    TimedMethod *sorted = sortTimedMethodList(list,  &num);
1494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    double methodTotal = method->elapsedInclusive;
1495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (pTimed = sorted; pTimed; pTimed = pTimed->next) {
1496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        MethodEntry *relative = pTimed->method;
1497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        className = (char*)(relative->className);
1498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodName = (char*)(relative->methodName);
1499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        signature = (char*)(relative->signature);
1500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        double per = 100.0 * pTimed->elapsedInclusive / methodTotal;
1501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sprintf(buf, "[%d]", relative->index);
1502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) {
1503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int len = strlen(buf);
1504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (len > num_spaces)
1505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                len = num_spaces;
1506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "<a href=\"#m%d\">[%d]",
1507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    relative->index, relative->index);
1508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            space_ptr = &spaces[len];
1509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            className = htmlEscape(className, classBuf, HTML_BUFSIZE);
1510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodName = htmlEscape(methodName, methodBuf, HTML_BUFSIZE);
1511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            signature = htmlEscape(signature, signatureBuf, HTML_BUFSIZE);
1512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int nCalls = numCalls;
1514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (nCalls == 0)
1515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            nCalls = relative->numCalls[0] + relative->numCalls[1];
1516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (relative->methodName) {
1517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (flags & kIsRecursive) {
1518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // Don't display percentages for recursive functions
1519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("%6s %5s   %6s %s%6s%s %6d/%-6d %9llu %s.%s %s\n",
1520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       "", "", "",
1521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       space_ptr, buf, anchor_close,
1522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       pTimed->numCalls, nCalls,
1523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       pTimed->elapsedInclusive,
1524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       className, methodName, signature);
1525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
1526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("%6s %5s   %5.1f%% %s%6s%s %6d/%-6d %9llu %s.%s %s\n",
1527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       "", "", per,
1528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       space_ptr, buf, anchor_close,
1529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       pTimed->numCalls, nCalls,
1530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       pTimed->elapsedInclusive,
1531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       className, methodName, signature);
1532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (flags & kIsRecursive) {
1535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // Don't display percentages for recursive functions
1536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("%6s %5s   %6s %s%6s%s %6d/%-6d %9llu %s\n",
1537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       "", "", "",
1538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       space_ptr, buf, anchor_close,
1539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       pTimed->numCalls, nCalls,
1540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       pTimed->elapsedInclusive,
1541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       className);
1542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
1543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("%6s %5s   %5.1f%% %s%6s%s %6d/%-6d %9llu %s\n",
1544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       "", "", per,
1545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       space_ptr, buf, anchor_close,
1546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       pTimed->numCalls, nCalls,
1547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       pTimed->elapsedInclusive,
1548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       className);
1549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid countRecursiveEntries(CallStack *pStack, int top, MethodEntry *method)
1555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii;
1557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->recursiveEntries = 0;
1559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < top; ++ii) {
1560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pStack->calls[ii].method == method)
1561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->recursiveEntries += 1;
1562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid stackDump(CallStack *pStack, int top)
1566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii;
1568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < top; ++ii) {
1570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        MethodEntry *method = pStack->calls[ii].method;
1571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        uint64_t entryTime = pStack->calls[ii].entryTime;
1572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method->methodName) {
1573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fprintf(stderr, "  %2d: %8llu %s.%s %s\n", ii, entryTime,
1574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   method->className, method->methodName, method->signature);
1575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fprintf(stderr, "  %2d: %8llu %s\n", ii, entryTime, method->className);
1577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid outputTableOfContents()
1582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("<a name=\"contents\"></a>\n");
1584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("<h2>Table of Contents</h2>\n");
1585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("<ul>\n");
1586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("  <li><a href=\"#exclusive\">Exclusive profile</a></li>\n");
1587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("  <li><a href=\"#inclusive\">Inclusive profile</a></li>\n");
15885b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    printf("  <li><a href=\"#thread\">Thread profile</a></li>\n");
1589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("  <li><a href=\"#class\">Class/method profile</a></li>\n");
1590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("  <li><a href=\"#method\">Method/class profile</a></li>\n");
1591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("</ul>\n\n");
1592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid outputNavigationBar()
1595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("<a href=\"#contents\">[Top]</a>\n");
1597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("<a href=\"#exclusive\">[Exclusive]</a>\n");
1598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("<a href=\"#inclusive\">[Inclusive]</a>\n");
15995b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    printf("<a href=\"#thread\">[Thread]</a>\n");
1600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("<a href=\"#class\">[Class]</a>\n");
1601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("<a href=\"#method\">[Method]</a>\n");
1602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("<br><br>\n");
1603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid printExclusiveProfile(MethodEntry **pMethods, int numMethods,
1606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                           uint64_t sumThreadTime)
1607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii;
1609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry* method;
1610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    double total, sum, per, sum_per;
1611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char classBuf[HTML_BUFSIZE], methodBuf[HTML_BUFSIZE];
1612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char signatureBuf[HTML_BUFSIZE];
1613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char anchor_buf[80];
1614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char *anchor_close = "";
1615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    total = sumThreadTime;
1617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    anchor_buf[0] = 0;
1618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
1619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        anchor_close = "</a>";
1620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<a name=\"exclusive\"></a>\n");
1621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<hr>\n");
1622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        outputNavigationBar();
1623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("\n%s\n", profileSeparator);
1625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* First, sort the methods into decreasing order of inclusive
1628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * elapsed time so that we can assign the method indices.
1629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(pMethods, numMethods, sizeof(MethodEntry*), compareElapsedInclusive);
1631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numMethods; ++ii)
1633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pMethods[ii]->index = ii;
1634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Sort the methods into decreasing order of exclusive elapsed time.
1636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(pMethods, numMethods, sizeof(MethodEntry*),
1638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project          compareElapsedExclusive);
1639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("Total cycles: %llu\n\n", sumThreadTime);
1641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
1642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<br><br>\n");
1643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("Exclusive elapsed times for each method, not including time spent in\n");
1645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("children, sorted by exclusive time.\n\n");
1646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
1647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<br><br>\n<pre>\n");
1648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("    Usecs  self %%  sum %%  Method\n");
1651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sum = 0;
1652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numMethods; ++ii) {
1654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char *className, *methodName, *signature;
1655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        method = pMethods[ii];
1657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Don't show methods with zero cycles */
1658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method->elapsedExclusive == 0)
1659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        className = (char*)(method->className);
1661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodName = (char*)(method->methodName);
1662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        signature = (char*)(method->signature);
1663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sum += method->elapsedExclusive;
1664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        per = 100.0 * method->elapsedExclusive / total;
1665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sum_per = 100.0 * sum / total;
1666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) {
1667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(anchor_buf, "<a href=\"#m%d\">", method->index);
1668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            className = htmlEscape(className, classBuf, HTML_BUFSIZE);
1669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodName = htmlEscape(methodName, methodBuf, HTML_BUFSIZE);
1670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            signature = htmlEscape(signature, signatureBuf, HTML_BUFSIZE);
1671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method->methodName) {
1673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("%9llu  %6.2f %6.2f  %s[%d]%s %s.%s %s\n",
1674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   method->elapsedExclusive, per, sum_per,
1675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   anchor_buf, method->index, anchor_close,
1676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   className, methodName, signature);
1677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("%9llu  %6.2f %6.2f  %s[%d]%s %s\n",
1679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   method->elapsedExclusive, per, sum_per,
1680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   anchor_buf, method->index, anchor_close,
1681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   className);
1682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
1685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("</pre>\n");
1686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* check to make sure that the child method meets the threshold of the parent */
1690de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiroint checkThreshold(MethodEntry* parent, MethodEntry* child)
1691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    double parentTime = parent->elapsedInclusive;
1693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    double childTime = child->elapsedInclusive;
1694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int64_t percentage = (childTime / parentTime) * 100.0;
1695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (percentage < gOptions.threshold) ? 0 : 1;
1696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid createLabels(FILE* file, MethodEntry* method)
1699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1700de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro    fprintf(file, "node%d[label = \"[%d] %s.%s (%llu, %llu, %d)\"]\n",
1701de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro             method->index, method->index, method->className, method->methodName,
1702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             method->elapsedInclusive / 1000,
1703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             method->elapsedExclusive / 1000,
1704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             method->numCalls[0]);
1705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1706de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro    method->graphState = GRAPH_LABEL_VISITED;
1707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    TimedMethod* child;
1709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (child = method->children[0] ; child ; child = child->next) {
1710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        MethodEntry* childMethod = child->method;
1711de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((childMethod->graphState & GRAPH_LABEL_VISITED) == 0 && checkThreshold(method, childMethod)) {
1713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            createLabels(file, child->method);
1714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid createLinks(FILE* file, MethodEntry* method)
1719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->graphState |= GRAPH_NODE_VISITED;
1721de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    TimedMethod* child;
1723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (child = method->children[0] ; child ; child = child->next) {
1724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        MethodEntry* childMethod = child->method;
1725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (checkThreshold(method, child->method)) {
1726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fprintf(file, "node%d -> node%d\n", method->index, child->method->index);
1727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // only visit children that haven't been visited before
1728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ((childMethod->graphState & GRAPH_NODE_VISITED) == 0) {
1729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                createLinks(file, child->method);
1730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid createInclusiveProfileGraphNew(DataKeys* dataKeys)
1736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // create a temporary file in /tmp
1738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char path[FILENAME_MAX];
1739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.keepDotFile) {
1740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        snprintf(path, FILENAME_MAX, "%s.dot", gOptions.graphFileName);
1741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        snprintf(path, FILENAME_MAX, "/tmp/dot-%d-%d.dot", (int)time(NULL), rand());
1743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    FILE* file = fopen(path, "w+");
1746de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(file, "digraph g {\nnode [shape = record,height=.1];\n");
1748de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    createLabels(file, dataKeys->methods);
1750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    createLinks(file, dataKeys->methods);
1751de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(file, "}");
1753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fclose(file);
1754de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // now that we have the dot file generate the image
1756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char command[1024];
1757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    snprintf(command, 1024, "dot -Tpng -o '%s' '%s'", gOptions.graphFileName, path);
1758de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    system(command);
1760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (! gOptions.keepDotFile) {
1762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        remove(path);
1763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid printInclusiveProfile(MethodEntry **pMethods, int numMethods,
1767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                           uint64_t sumThreadTime)
1768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii;
1770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry* method;
1771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    double total, sum, per, sum_per;
1772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char classBuf[HTML_BUFSIZE], methodBuf[HTML_BUFSIZE];
1773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char signatureBuf[HTML_BUFSIZE];
1774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char anchor_buf[80];
1775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    total = sumThreadTime;
1777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    anchor_buf[0] = 0;
1778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
1779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<a name=\"inclusive\"></a>\n");
1780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<hr>\n");
1781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        outputNavigationBar();
1782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("\n%s\n", profileSeparator);
1784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Sort the methods into decreasing order of inclusive elapsed time. */
1787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(pMethods, numMethods, sizeof(MethodEntry*),
1788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project          compareElapsedInclusive);
1789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("\nInclusive elapsed times for each method and its parents and children,\n");
1791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("sorted by inclusive time.\n\n");
1792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
1794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<br><br>\n<pre>\n");
1795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("index  %%/total %%/self  index     calls         usecs name\n");
1798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numMethods; ++ii) {
1799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int num;
1800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        TimedMethod *pTimed;
1801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        double excl_per;
1802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char buf[40];
1803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char *className, *methodName, *signature;
1804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        method = pMethods[ii];
1806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Don't show methods with zero cycles */
1807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method->elapsedInclusive == 0)
1808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        className = (char*)(method->className);
1811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodName = (char*)(method->methodName);
1812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        signature = (char*)(method->signature);
1813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) {
1815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("<a name=\"m%d\"></a>", method->index);
1816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            className = htmlEscape(className, classBuf, HTML_BUFSIZE);
1817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodName = htmlEscape(methodName, methodBuf, HTML_BUFSIZE);
1818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            signature = htmlEscape(signature, signatureBuf, HTML_BUFSIZE);
1819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("----------------------------------------------------\n");
1821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Sort and print the parents */
1823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int numCalls = method->numCalls[0] + method->numCalls[1];
1824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printInclusiveMethod(method, method->parents[0], numCalls, 0);
1825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method->parents[1]) {
1826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("               +++++++++++++++++++++++++\n");
1827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printInclusiveMethod(method, method->parents[1], numCalls,
1828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                 kIsRecursive);
1829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        per = 100.0 * method->elapsedInclusive / total;
1832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sprintf(buf, "[%d]", ii);
1833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method->methodName) {
1834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("%-6s %5.1f%%   %5s %6s %6d+%-6d %9llu %s.%s %s\n",
1835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   buf,
1836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   per, "", "", method->numCalls[0], method->numCalls[1],
1837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   method->elapsedInclusive,
1838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   className, methodName, signature);
1839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("%-6s %5.1f%%   %5s %6s %6d+%-6d %9llu %s\n",
1841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   buf,
1842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   per, "", "", method->numCalls[0], method->numCalls[1],
1843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   method->elapsedInclusive,
1844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   className);
1845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        excl_per = 100.0 * method->topExclusive / method->elapsedInclusive;
1847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%6s %5s   %5.1f%% %6s %6s %6s %9llu\n",
1848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               "", "", excl_per, "excl", "", "", method->topExclusive);
1849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Sort and print the children */
1851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printInclusiveMethod(method, method->children[0], 0, 0);
1852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method->children[1]) {
1853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("               +++++++++++++++++++++++++\n");
1854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printInclusiveMethod(method, method->children[1], 0,
1855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                 kIsRecursive);
1856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
1859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("</pre>\n");
1860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
18636978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipincevoid printThreadProfile(ThreadEntry *pThreads, int numThreads, uint64_t sumThreadTime, Filter** filters)
18645b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince{
18656978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int ii, jj;
18665b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    ThreadEntry thread;
18675b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    double total, per, sum_per;
18685b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    uint64_t sum;
18695b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    char threadBuf[HTML_BUFSIZE];
18705b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    char anchor_buf[80];
18716978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int drawTable;
18725b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
18735b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    total = sumThreadTime;
18745b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    anchor_buf[0] = 0;
18755b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    if (gOptions.outputHtml) {
18765b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        printf("<a name=\"thread\"></a>\n");
18775b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        printf("<hr>\n");
18785b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        outputNavigationBar();
18795b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    } else {
18805b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        printf("\n%s\n", profileSeparator);
18815b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    }
18825b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
18835b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    /* Sort the threads into decreasing order of elapsed time. */
18845b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    qsort(pThreads, numThreads, sizeof(ThreadEntry), compareElapsed);
18855b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
18866978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    printf("\nElapsed times for each thread, sorted by elapsed time.\n");
18876978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    printf("Also includes percentage of time spent during the <i>execution</i> of any filters.\n\n");
18885b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
18895b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    if (gOptions.outputHtml) {
18905b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        printf("<br><br>\n<pre>\n");
18915b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    }
18925b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
18936978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    printf("    Usecs   self %%  sum %%");
18946978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    for (ii = 0; ii < numFilters; ++ii) {
18956978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        printf("  %s %%", filters[ii]->filterName);
18966978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    }
18976978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    printf("  tid   ThreadName\n");
18985b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    sum = 0;
18995b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
19005b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    for (ii = 0; ii < numThreads; ++ii) {
19015b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        int threadId;
19025b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        char *threadName;
19035b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        uint64_t time;
19045b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
19055b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        thread = pThreads[ii];
19065b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
19075b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        threadId = thread.threadId;
19085b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        threadName = (char*)(thread.threadName);
19095b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        time = thread.elapsedTime;
19105b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
19115b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        sum += time;
19125b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        per = 100.0 * time / total;
19135b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        sum_per = 100.0 * sum / total;
19145b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
19155b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        if (gOptions.outputHtml) {
19165b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince	    threadName = htmlEscape(threadName, threadBuf, HTML_BUFSIZE);
19175b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        }
19186978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
19196978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	printf("%9llu  %6.2f %6.2f", time, per, sum_per);
19206978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	for (jj = 0; jj < numFilters; jj++) {
19216978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    printf(" %6.2f", 100.0 * filters[jj]->times.threadExecutionTimes[threadId] / time);
19226978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	}
19236978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	printf("    %3d %s\n", threadId, threadName);
19245b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    }
19255b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
19265b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    if (gOptions.outputHtml)
19276978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        printf("</pre><br />");
19286978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
19296978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    printf("\n\nBreak-down of portion of time spent by each thread while waiting on a filter method.\n");
19306978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
19316978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    for (ii = 0; ii < numFilters; ++ii) {
19326978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        // Draw a table for each filter that measures wait time
19336978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        drawTable = 0;
19346978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	for (jj = 0; jj < filters[ii]->numKeys; jj++)
19356978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    if (filters[ii]->filterKeys[jj].flags == 1)
19366978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        drawTable = 1;
19376978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
19386978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	if (drawTable) {
19396978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
19406978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    if (gOptions.outputHtml)
19416978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        printf("<br/><br/>\n<pre>\n");
19426978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    printf("Filter: %s\n", filters[ii]->filterName);
19436978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    printf("Total waiting cycles: %llu (%6.2f%% of total)\n",
19446978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		   filters[ii]->times.totalWaitTime,
19456978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		   100.0 * filters[ii]->times.totalWaitTime / sum);
19466978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
19476978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    if (filters[ii]->times.totalWaitTime > 0) {
19486978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
19496978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        printf("Details: \n\n");
19506978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
19516978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		printf(" Waiting cycles    %% of total waiting time   execution time while waiting    thread name\n");
19526978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
19536978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		for (jj = 0; jj < numThreads; jj++) {
19546978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
19556978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    thread = pThreads[jj];
19566978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
19576978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    char *threadName;
19586978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    threadName = (char*) thread.threadName;
19596978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    if (gOptions.outputHtml) {
19606978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		        threadName = htmlEscape(threadName, threadBuf, HTML_BUFSIZE);
19616978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    }
19626978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
19636978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    printf(" %9llu                   %6.2f                     %6.2f               %s\n",
19646978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince			   filters[ii]->times.threadWaitTimes[thread.threadId],
19656978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince			   100.0 * filters[ii]->times.threadWaitTimes[thread.threadId] / filters[ii]->times.totalWaitTime,
19666978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince			   100.0 * filters[ii]->times.threadExecutionTimesWhileWaiting[thread.threadId] / filters[ii]->times.totalWaitTime,
19676978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince			   threadName);
19686978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		}
19696978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    }
19706978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
19716978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    if (gOptions.outputHtml)
19726978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        printf("</pre>\n");
19736978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
19746978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	}
19756978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    }
19765b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
19775b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince}
19785b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
1979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid createClassList(TraceData* traceData, MethodEntry **pMethods, int numMethods)
1980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii;
1982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Sort the methods into alphabetical order to find the unique class
1984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * names.
1985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(pMethods, numMethods, sizeof(MethodEntry*), compareClassNames);
1987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Count the number of unique class names. */
1989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char *currentClassName = "";
1990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char *firstClassName = NULL;
1991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    traceData->numClasses = 0;
1992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numMethods; ++ii) {
1993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pMethods[ii]->methodName == NULL) {
1994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
1995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(pMethods[ii]->className, currentClassName) != 0) {
1997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Remember the first one
1998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (firstClassName == NULL) {
1999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                firstClassName = pMethods[ii]->className;
2000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            traceData->numClasses += 1;
2002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            currentClassName = pMethods[ii]->className;
2003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (traceData->numClasses == 0) {
2007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        traceData->classes = NULL;
2008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
2009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Allocate space for all of the unique class names */
2012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    traceData->classes = (ClassEntry *) malloc(sizeof(ClassEntry) * traceData->numClasses);
2013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Initialize the classes array */
2015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(traceData->classes, 0, sizeof(ClassEntry) * traceData->numClasses);
2016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassEntry *pClass = traceData->classes;
2017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pClass->className = currentClassName = firstClassName;
2018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int prevNumMethods = 0;
2019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numMethods; ++ii) {
2020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pMethods[ii]->methodName == NULL) {
2021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
2022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(pMethods[ii]->className, currentClassName) != 0) {
2024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pClass->numMethods = prevNumMethods;
2025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (++pClass)->className = currentClassName = pMethods[ii]->className;
2026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            prevNumMethods = 0;
2027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        prevNumMethods += 1;
2029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pClass->numMethods = prevNumMethods;
2031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Create the array of MethodEntry pointers for each class */
2033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pClass = NULL;
2034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    currentClassName = "";
2035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int nextMethod = 0;
2036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numMethods; ++ii) {
2037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pMethods[ii]->methodName == NULL) {
2038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
2039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(pMethods[ii]->className, currentClassName) != 0) {
2041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            currentClassName = pMethods[ii]->className;
2042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (pClass == NULL)
2043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pClass = traceData->classes;
2044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            else
2045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pClass++;
2046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Allocate space for the methods array */
2047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int nbytes = sizeof(MethodEntry*) * pClass->numMethods;
2048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pClass->methods = (MethodEntry**) malloc(nbytes);
2049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            nextMethod = 0;
2050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pClass->methods[nextMethod++] = pMethods[ii];
2052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Prints a number of html non-breaking spaces according so that the length
2056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of the string "buf" is at least "width" characters wide.  If width is
2057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * negative, then trailing spaces are added instead of leading spaces.
2058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid printHtmlField(char *buf, int width)
2060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii;
2062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int leadingSpaces = 1;
2064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (width < 0) {
2065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        width = -width;
2066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        leadingSpaces = 0;
2067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int len = strlen(buf);
2069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numSpaces = width - len;
2070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (numSpaces <= 0) {
2071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%s", buf);
2072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
2073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (leadingSpaces == 0)
2075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%s", buf);
2076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numSpaces; ++ii)
2077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("&nbsp;");
2078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (leadingSpaces == 1)
2079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%s", buf);
2080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid printClassProfiles(TraceData* traceData, uint64_t sumThreadTime)
2083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii, jj;
2085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry* method;
2086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    double total, sum, per, sum_per;
2087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char classBuf[HTML_BUFSIZE], methodBuf[HTML_BUFSIZE];
2088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char signatureBuf[HTML_BUFSIZE];
2089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    total = sumThreadTime;
2091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
2092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<a name=\"class\"></a>\n");
2093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<hr>\n");
2094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        outputNavigationBar();
2095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("\n%s\n", profileSeparator);
2097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (traceData->numClasses == 0) {
2100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("\nNo classes.\n");
2101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) {
2102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("<br><br>\n");
2103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
2105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("\nExclusive elapsed time for each class, summed over all the methods\n");
2108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("in the class.\n\n");
2109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
2110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<br><br>\n");
2111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* For each class, sum the exclusive times in all of the methods
2114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in that class.  Also sum the number of method calls.  Also
2115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * sort the methods so the most expensive appear at the top.
2116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassEntry *pClass = traceData->classes;
2118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < traceData->numClasses; ++ii, ++pClass) {
2119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //printf("%s %d methods\n", pClass->className, pClass->numMethods);
2120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int numMethods = pClass->numMethods;
2121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (jj = 0; jj < numMethods; ++jj) {
2122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method = pClass->methods[jj];
2123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pClass->elapsedExclusive += method->elapsedExclusive;
2124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pClass->numCalls[0] += method->numCalls[0];
2125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pClass->numCalls[1] += method->numCalls[1];
2126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Sort the methods into decreasing order of exclusive time */
2129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        qsort(pClass->methods, numMethods, sizeof(MethodEntry*),
2130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project              compareElapsedExclusive);
2131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Allocate an array of pointers to the classes for more efficient
2134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * sorting.
2135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassEntry **pClasses;
2137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pClasses = (ClassEntry**) malloc(sizeof(ClassEntry*) * traceData->numClasses);
2138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < traceData->numClasses; ++ii)
2139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pClasses[ii] = &traceData->classes[ii];
2140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Sort the classes into decreasing order of exclusive time */
2142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(pClasses, traceData->numClasses, sizeof(ClassEntry*), compareClassExclusive);
2143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
2145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<div class=\"header\"><span class=\"parent\">&nbsp;</span>&nbsp;&nbsp;&nbsp;");
2146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("Cycles %%/total Cumul.%% &nbsp;Calls+Recur&nbsp; Class</div>\n");
2147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("   Cycles %%/total Cumul.%%  Calls+Recur  Class\n");
2149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sum = 0;
2152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < traceData->numClasses; ++ii) {
2153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char *className, *methodName, *signature;
2154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Skip classes with zero cycles */
2156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pClass = pClasses[ii];
2157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pClass->elapsedExclusive == 0)
2158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
2159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        per = 100.0 * pClass->elapsedExclusive / total;
2161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sum += pClass->elapsedExclusive;
2162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sum_per = 100.0 * sum / total;
2163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        className = (char*)(pClass->className);
2164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) {
2165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            char buf[80];
2166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            className = htmlEscape(className, classBuf, HTML_BUFSIZE);
2168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("<div class=\"link\" onClick=\"javascript:toggle('d%d')\" onMouseOver=\"javascript:onMouseOver(this)\" onMouseOut=\"javascript:onMouseOut(this)\"><span class=\"parent\" id=\"xd%d\">+</span>", ii, ii);
2169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "%llu", pClass->elapsedExclusive);
2170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printHtmlField(buf, 9);
2171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" ");
2172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "%.1f", per);
2173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printHtmlField(buf, 7);
2174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" ");
2175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "%.1f", sum_per);
2176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printHtmlField(buf, 7);
2177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" ");
2178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "%d", pClass->numCalls[0]);
2179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printHtmlField(buf, 6);
2180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("+");
2181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "%d", pClass->numCalls[1]);
2182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printHtmlField(buf, -6);
2183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" ");
2184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("%s", className);
2185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("</div>\n");
2186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("<div class=\"parent\" id=\"d%d\">\n", ii);
2187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
2188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("---------------------------------------------\n");
2189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("%9llu %7.1f %7.1f %6d+%-6d %s\n",
2190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   pClass->elapsedExclusive, per, sum_per,
2191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   pClass->numCalls[0], pClass->numCalls[1],
2192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   className);
2193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int numMethods = pClass->numMethods;
2196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        double classExclusive = pClass->elapsedExclusive;
2197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        double sumMethods = 0;
2198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (jj = 0; jj < numMethods; ++jj) {
2199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method = pClass->methods[jj];
2200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodName = (char*)(method->methodName);
2201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            signature = (char*)(method->signature);
2202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            per = 100.0 * method->elapsedExclusive / classExclusive;
2203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sumMethods += method->elapsedExclusive;
2204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sum_per = 100.0 * sumMethods / classExclusive;
2205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (gOptions.outputHtml) {
2206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                char buf[80];
2207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                methodName = htmlEscape(methodName, methodBuf, HTML_BUFSIZE);
2209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                signature = htmlEscape(signature, signatureBuf, HTML_BUFSIZE);
2210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("<div class=\"leaf\"><span class=\"leaf\">&nbsp;</span>");
2211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%llu", method->elapsedExclusive);
2212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, 9);
2213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("&nbsp;");
2214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%llu", method->elapsedInclusive);
2215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, 9);
2216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("&nbsp;");
2217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%.1f", per);
2218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, 7);
2219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("&nbsp;");
2220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%.1f", sum_per);
2221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, 7);
2222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("&nbsp;");
2223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%d", method->numCalls[0]);
2224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, 6);
2225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("+");
2226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%d", method->numCalls[1]);
2227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, -6);
2228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("&nbsp;");
2229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("<a href=\"#m%d\">[%d]</a>&nbsp;%s&nbsp;%s",
2230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       method->index, method->index, methodName, signature);
2231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("</div>\n");
2232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
2233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("%9llu %9llu %7.1f %7.1f %6d+%-6d [%d] %s %s\n",
2234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       method->elapsedExclusive,
2235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       method->elapsedInclusive,
2236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       per, sum_per,
2237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       method->numCalls[0], method->numCalls[1],
2238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       method->index, methodName, signature);
2239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) {
2242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("</div>\n");
2243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid createUniqueMethodList(TraceData* traceData, MethodEntry **pMethods, int numMethods)
2248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii;
2250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Sort the methods into alphabetical order of method names
2252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to find the unique method names.
2253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(pMethods, numMethods, sizeof(MethodEntry*), compareMethodNames);
2255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Count the number of unique method names, ignoring class and
2257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * signature.
2258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char *currentMethodName = "";
2260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    traceData->numUniqueMethods = 0;
2261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numMethods; ++ii) {
2262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pMethods[ii]->methodName == NULL)
2263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
2264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(pMethods[ii]->methodName, currentMethodName) != 0) {
2265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            traceData->numUniqueMethods += 1;
2266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            currentMethodName = pMethods[ii]->methodName;
2267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (traceData->numUniqueMethods == 0)
2270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
2271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Allocate space for pointers to all of the unique methods */
2273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int nbytes = sizeof(UniqueMethodEntry) * traceData->numUniqueMethods;
2274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    traceData->uniqueMethods = (UniqueMethodEntry *) malloc(nbytes);
2275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Initialize the uniqueMethods array */
2277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(traceData->uniqueMethods, 0, nbytes);
2278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UniqueMethodEntry *pUnique = traceData->uniqueMethods;
2279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    currentMethodName = NULL;
2280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int prevNumMethods = 0;
2281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numMethods; ++ii) {
2282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pMethods[ii]->methodName == NULL)
2283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
2284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (currentMethodName == NULL)
2285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            currentMethodName = pMethods[ii]->methodName;
2286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(pMethods[ii]->methodName, currentMethodName) != 0) {
2287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            currentMethodName = pMethods[ii]->methodName;
2288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pUnique->numMethods = prevNumMethods;
2289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pUnique++;
2290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            prevNumMethods = 0;
2291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        prevNumMethods += 1;
2293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pUnique->numMethods = prevNumMethods;
2295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Create the array of MethodEntry pointers for each unique method */
2297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pUnique = NULL;
2298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    currentMethodName = "";
2299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int nextMethod = 0;
2300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numMethods; ++ii) {
2301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pMethods[ii]->methodName == NULL)
2302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
2303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(pMethods[ii]->methodName, currentMethodName) != 0) {
2304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            currentMethodName = pMethods[ii]->methodName;
2305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (pUnique == NULL)
2306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pUnique = traceData->uniqueMethods;
2307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            else
2308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pUnique++;
2309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Allocate space for the methods array */
2310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int nbytes = sizeof(MethodEntry*) * pUnique->numMethods;
2311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pUnique->methods = (MethodEntry**) malloc(nbytes);
2312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            nextMethod = 0;
2313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pUnique->methods[nextMethod++] = pMethods[ii];
2315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid printMethodProfiles(TraceData* traceData, uint64_t sumThreadTime)
2319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii, jj;
2321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry* method;
2322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    double total, sum, per, sum_per;
2323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char classBuf[HTML_BUFSIZE], methodBuf[HTML_BUFSIZE];
2324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char signatureBuf[HTML_BUFSIZE];
2325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (traceData->numUniqueMethods == 0)
2327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
2328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    total = sumThreadTime;
2330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
2331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<a name=\"method\"></a>\n");
2332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<hr>\n");
2333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        outputNavigationBar();
2334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("\n%s\n", profileSeparator);
2336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("\nExclusive elapsed time for each method, summed over all the classes\n");
2339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("that contain a method with the same name.\n\n");
2340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
2341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<br><br>\n");
2342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* For each unique method, sum the exclusive times in all of the methods
2345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * with the same name.  Also sum the number of method calls.  Also
2346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * sort the methods so the most expensive appear at the top.
2347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UniqueMethodEntry *pUnique = traceData->uniqueMethods;
2349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < traceData->numUniqueMethods; ++ii, ++pUnique) {
2350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int numMethods = pUnique->numMethods;
2351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (jj = 0; jj < numMethods; ++jj) {
2352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method = pUnique->methods[jj];
2353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pUnique->elapsedExclusive += method->elapsedExclusive;
2354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pUnique->numCalls[0] += method->numCalls[0];
2355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pUnique->numCalls[1] += method->numCalls[1];
2356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Sort the methods into decreasing order of exclusive time */
2359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        qsort(pUnique->methods, numMethods, sizeof(MethodEntry*),
2360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project              compareElapsedExclusive);
2361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Allocate an array of pointers to the methods for more efficient
2364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * sorting.
2365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UniqueMethodEntry **pUniqueMethods;
2367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int nbytes = sizeof(UniqueMethodEntry*) * traceData->numUniqueMethods;
2368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pUniqueMethods = (UniqueMethodEntry**) malloc(nbytes);
2369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < traceData->numUniqueMethods; ++ii)
2370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pUniqueMethods[ii] = &traceData->uniqueMethods[ii];
2371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Sort the methods into decreasing order of exclusive time */
2373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(pUniqueMethods, traceData->numUniqueMethods, sizeof(UniqueMethodEntry*),
2374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project          compareUniqueExclusive);
2375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
2377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<div class=\"header\"><span class=\"parent\">&nbsp;</span>&nbsp;&nbsp;&nbsp;");
2378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("Cycles %%/total Cumul.%% &nbsp;Calls+Recur&nbsp; Method</div>\n");
2379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("   Cycles %%/total Cumul.%%  Calls+Recur  Method\n");
2381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sum = 0;
2384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < traceData->numUniqueMethods; ++ii) {
2385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char *className, *methodName, *signature;
2386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Skip methods with zero cycles */
2388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pUnique = pUniqueMethods[ii];
2389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pUnique->elapsedExclusive == 0)
2390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
2391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        per = 100.0 * pUnique->elapsedExclusive / total;
2393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sum += pUnique->elapsedExclusive;
2394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sum_per = 100.0 * sum / total;
2395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodName = (char*)(pUnique->methods[0]->methodName);
2396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) {
2397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            char buf[80];
2398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodName = htmlEscape(methodName, methodBuf, HTML_BUFSIZE);
2400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("<div class=\"link\" onClick=\"javascript:toggle('e%d')\" onMouseOver=\"javascript:onMouseOver(this)\" onMouseOut=\"javascript:onMouseOut(this)\"><span class=\"parent\" id=\"xe%d\">+</span>", ii, ii);
2401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "%llu", pUnique->elapsedExclusive);
2402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printHtmlField(buf, 9);
2403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" ");
2404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "%.1f", per);
2405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printHtmlField(buf, 7);
2406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" ");
2407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "%.1f", sum_per);
2408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printHtmlField(buf, 7);
2409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" ");
2410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "%d", pUnique->numCalls[0]);
2411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printHtmlField(buf, 6);
2412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("+");
2413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "%d", pUnique->numCalls[1]);
2414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printHtmlField(buf, -6);
2415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" ");
2416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("%s", methodName);
2417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("</div>\n");
2418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("<div class=\"parent\" id=\"e%d\">\n", ii);
2419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
2420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("---------------------------------------------\n");
2421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("%9llu %7.1f %7.1f %6d+%-6d %s\n",
2422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   pUnique->elapsedExclusive, per, sum_per,
2423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   pUnique->numCalls[0], pUnique->numCalls[1],
2424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   methodName);
2425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int numMethods = pUnique->numMethods;
2427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        double methodExclusive = pUnique->elapsedExclusive;
2428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        double sumMethods = 0;
2429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (jj = 0; jj < numMethods; ++jj) {
2430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method = pUnique->methods[jj];
2431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            className = (char*)(method->className);
2432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            signature = (char*)(method->signature);
2433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            per = 100.0 * method->elapsedExclusive / methodExclusive;
2434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sumMethods += method->elapsedExclusive;
2435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sum_per = 100.0 * sumMethods / methodExclusive;
2436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (gOptions.outputHtml) {
2437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                char buf[80];
2438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                className = htmlEscape(className, classBuf, HTML_BUFSIZE);
2440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                signature = htmlEscape(signature, signatureBuf, HTML_BUFSIZE);
2441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("<div class=\"leaf\"><span class=\"leaf\">&nbsp;</span>");
2442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%llu", method->elapsedExclusive);
2443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, 9);
2444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("&nbsp;");
2445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%llu", method->elapsedInclusive);
2446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, 9);
2447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("&nbsp;");
2448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%.1f", per);
2449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, 7);
2450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("&nbsp;");
2451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%.1f", sum_per);
2452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, 7);
2453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("&nbsp;");
2454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%d", method->numCalls[0]);
2455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, 6);
2456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("+");
2457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%d", method->numCalls[1]);
2458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, -6);
2459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("&nbsp;");
2460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("<a href=\"#m%d\">[%d]</a>&nbsp;%s.%s&nbsp;%s",
2461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       method->index, method->index,
2462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       className, methodName, signature);
2463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("</div>\n");
2464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
2465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("%9llu %9llu %7.1f %7.1f %6d+%-6d [%d] %s.%s %s\n",
2466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       method->elapsedExclusive,
2467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       method->elapsedInclusive,
2468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       per, sum_per,
2469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       method->numCalls[0], method->numCalls[1],
2470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       method->index, className, methodName, signature);
2471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) {
2474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("</div>\n");
2475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
24806978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * Determines whether the given FilterKey matches the method. The FilterKey's
24816978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * key that is used to match against the method is determined by index.
24826978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince */
24836978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipinceint keyMatchesMethod(FilterKey filterKey, MethodEntry* method, int index)
24846978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince{
24856978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    if (filterKey.type[index] == 0) { // Class
24866978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince#if 0
24876978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        fprintf(stderr, "  class is %s; filter key is %s\n", method->className, filterKey.keys[index]);
24886978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince#endif
24896978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        if (strcmp(method->className, filterKey.keys[index]) == 0) {
24906978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    return 1;
24916978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	}
24926978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    } else { // Method
24936978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        if (method->methodName != NULL) {
24946978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    // Get fully-qualified name
24956978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince            // TODO: parse class name and method name an put them in structure to avoid
24966978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince            // allocating memory here
24976978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    char* str = malloc ((strlen(method->className) + strlen(method->methodName) + 2) * sizeof(char));
24986978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    strcpy(str, method->className);
24996978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    strcat(str, ".");
25006978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    strcat(str, method->methodName);
25016978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince#if 0
25026978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    fprintf(stderr, "  method is %s; filter key is %s\n", str, filterKey.keys[index]);
25036978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince#endif
25046978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    if (strcmp(str, filterKey.keys[index]) == 0) {
25056978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        free(str);
25066978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        return 1;
25076978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    }
25086978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    free(str);
25096978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	}
25106978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    }
25116978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    return 0;
25126978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince}
25136978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
25146978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince/*
25156978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * Adds the appropriate times to the given filter based on the given method. Activates and
25166978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * de-activates filters as necessary.
25176978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince *
25186978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * A filter is activated when the given method matches the 'entry' key of one of its FilterKeys.
25196978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * It is de-activated when the method matches the 'exit' key of the same FilterKey that activated it
25206978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * in the first place. Thus, a filter may be active more than once on the same thread (activated by
25216978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * different FilterKeys). A filter may also be active on different threads at the same time.
25226978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince *
25236978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * While the filter is active on thread 1, elapsed time is allocated to different buckets which
25246978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * include: thread execution time (i.e., time thread 1 spent executing while filter was active),
25256978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * thread waiting time (i.e., time thread 1 waited while other threads executed), and execution
25266978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * time while waiting (i.e., time thread x spent executing while thread 1 was waiting). We also
25276978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * keep track of the total waiting time for a given filter.
25286978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince *
25296978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * Lastly, we keep track of remaining (un-allocated) time for cases in which we exit a method we
25306978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * had not entered before, and that method happens to match the 'exit' key of a FilterKey.
25316978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince */
25326978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipinceint filterMethod(MethodEntry* method, Filter* filter, int entry, int threadId, int numThreads,
25336978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		 uint64_t elapsed, uint64_t remTime)
25346978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince{
25356978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int ii, jj;
25366978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int activeCount, addedWaitTimeThreadsCount;
25376978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int* activeThreads;
25386978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int* activationKeys;
25396978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int* addedWaitTimeThreads;
25406978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
25416978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    // flags
25426978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int addWaitTime = 0;
25436978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int deactivation = 0;
25446978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int addedExecutionTime = 0;
25456978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int addedExecutionTimeWhileWaiting = 0;
25466978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int addedWaitTime;
25476978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int addedRemTime = 0;
25486978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int threadKeyPairActive = 0;
25496978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
25506978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    if (filter->times.threadWaitTimes == NULL && filter->times.threadExecutionTimes == NULL &&
25516978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	filter->times.threadExecutionTimesWhileWaiting == NULL) {
25526978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        filter->times.threadWaitTimes = (uint64_t*) calloc(MAX_THREADS, sizeof(uint64_t));
25536978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	filter->times.threadExecutionTimesWhileWaiting =
25546978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince          (uint64_t*) calloc(MAX_THREADS, sizeof(uint64_t));
25556978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	filter->times.threadExecutionTimes = (uint64_t*) calloc(MAX_THREADS, sizeof(uint64_t));
25566978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    }
25576978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
25586978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int verbose = 0;
25596978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
25606978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    if (verbose)
25616978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        fprintf(stderr,
25626978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince                "Running %s filter for class %s method %s, thread %d; activeCount: %d time: %llu\n",
25636978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince                filter->filterName, method->className, method->methodName, threadId,
25646978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince                filter->activeCount, elapsed);
25656978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
25666978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    // If active on some thread
25676978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    if (filter->activeCount > 0) {
25686978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
25696978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        // Initialize active structures in case there are any de-activations
25706978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        activeThreads = (int*) calloc(filter->activeCount, sizeof(int));
25716978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	activationKeys = (int*) calloc(filter->activeCount, sizeof(int));
25726978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	activeCount = 0;
25736978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
25746978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	// Initialize structure to help us determine which threads we've already added wait time to
25756978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	addedWaitTimeThreads = (int*) calloc(filter->activeCount, sizeof(int));
25766978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	addedWaitTimeThreadsCount = 0;
25776978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
25786978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        // Add times to appropriate sums and de-activate (if necessary)
25796978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        for (ii = 0; ii < filter->activeCount; ii++) {
25806978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
25816978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    if (verbose) {
25826978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        fprintf(stderr, "  Analyzing active thread with id %d, activated by key [%s, %s]\n",
25836978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince			filter->activeThreads[ii],
25846978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince                        filter->filterKeys[filter->activationKeys[ii]].keys[0],
25856978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince			filter->filterKeys[filter->activationKeys[ii]].keys[1]);
25866978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    }
25876978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
25886978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    // If active on THIS thread -> add to execution time (only add once!)
25896978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    if (filter->activeThreads[ii] == threadId && !addedExecutionTime) {
25906978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        if (verbose)
25916978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    fprintf(stderr, "  Adding execution time to this thead\n");
25926978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        filter->times.threadExecutionTimes[threadId] += elapsed;
25936978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		addedExecutionTime = 1;
25946978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    }
25956978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
25966978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    // If active on ANOTHER thread (or this one too) with CROSS_THREAD_FLAG -> add to
25976978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince            // both thread's waiting time + total
25986978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    if (filter->filterKeys[filter->activationKeys[ii]].flags == 1) {
25996978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
26006978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        // Add time to thread that is waiting (add to each waiting thread at most once!)
26016978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        addedWaitTime = 0;
26026978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		for (jj = 0; jj < addedWaitTimeThreadsCount; jj++) {
26036978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    if (addedWaitTimeThreads[jj] == filter->activeThreads[ii])
26046978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		        addedWaitTime = 1;
26056978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		}
26066978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        if (!addedWaitTime) {
26076978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    if (verbose)
26086978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		        fprintf(stderr, "  Adding wait time to waiting thread\n");
26096978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    filter->times.threadWaitTimes[filter->activeThreads[ii]] += elapsed;
26106978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    addedWaitTimeThreads[addedWaitTimeThreadsCount++] = filter->activeThreads[ii];
26116978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		}
26126978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
26136978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince                // Add execution time to this thread while the other is waiting (only add once!)
26146978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince                // [Flag is needed only because outside for loop might iterate through same
26156978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince                // thread twice?] TODO: verify
26166978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		if (!addedExecutionTimeWhileWaiting) {
26176978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    if (verbose)
26186978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		        fprintf(stderr, "  Adding exec time to this thread while thread waits\n");
26196978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    filter->times.threadExecutionTimesWhileWaiting[threadId] += elapsed;
26206978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    addedExecutionTimeWhileWaiting = 1;
26216978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		}
26226978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
26236978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		addWaitTime = 1;
26246978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    }
26256978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
26266978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    // If a method exit matches the EXIT method of an ACTIVE key -> de-activate
26276978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince            // the KEY (not the entire filter!!)
26286978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    if (!entry && keyMatchesMethod(filter->filterKeys[filter->activationKeys[ii]],
26296978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince					   method, 1)) {
26306978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        if (verbose)
26316978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    fprintf(stderr, "  Exit key matched!\n");
26326978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
26336978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        // Deactivate by removing (NOT adding) entries from activeThreads and activationKeys
26346978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        deactivation = 1; // singal that lists should be replaced
26356978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    } else {
26366978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        // No de-activation -> copy old entries into new lists
26376978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        activeThreads[activeCount] = filter->activeThreads[ii];
26386978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		activationKeys[activeCount++] = filter->activationKeys[ii];
26396978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    }
26406978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	}
26416978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
26426978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	// If waiting on ANY thread, add wait time to total (but only ONCE!)
26436978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	if (addWaitTime) {
26446978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    filter->times.totalWaitTime += elapsed;
26456978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	}
26466978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
26476978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	// If de-activation occurred, replace lists
26486978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	if (deactivation) {
26496978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    // TODO: Free memory from old lists
26506978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
26516978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    // Set new lists
26526978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    filter->activeThreads = activeThreads;
26536978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    filter->activationKeys = activationKeys;
26546978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    filter->activeCount = activeCount;
26556978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	} else {
26566978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    // TODO: Free memory from new lists
26576978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	}
26586978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
26596978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    }  // Else, continue (we might be activating the filter on a different thread)
26606978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
26616978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
26626978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    if (entry) { // ENTRY
26636978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        if (verbose)
26646978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    fprintf(stderr, "  Here at the entry\n");
26656978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        // If method matches entry key -> activate thread (do not add time since it's a new entry!)
26666978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        for (ii = 0; ii < filter->numKeys; ii++) {
26676978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    if (keyMatchesMethod(filter->filterKeys[ii], method, 0)) {
26686978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        if (verbose)
26696978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    fprintf(stderr, "  Entry key matched!\n");
26706978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        // Activate thread only if thread/key pair is not already active
26716978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        for (jj = 0; jj < filter->activeCount; jj++) {
26726978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    if (filter->activeThreads[jj] == threadId && filter->activationKeys[jj] == ii)
26736978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		        threadKeyPairActive = 1;
26746978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		}
26756978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        // TODO: WORRY ABOUT MEMORY WHEN ACTIVE_COUNT > DEFAULT_ACTIVE_THREAD (unlikely)
26766978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        // TODO: what if the same thread is active multiple times by different keys?
26776978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		// nothing, we just have to make sure we dont double-add, and we dont..
26786978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		if (!threadKeyPairActive) {
26796978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    filter->activeThreads[filter->activeCount] = threadId;
26806978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    filter->activationKeys[filter->activeCount++] = ii;
26816978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		}
26826978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    }
26836978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	}
26846978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    } else { // EXIT
26856978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        // If method matches a terminal key -> add remTime to total (no need to active/de-activate)
26866978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        for (ii = 0; ii < filter->numKeys; ii++) {
26876978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    if (!deactivation && keyMatchesMethod(filter->filterKeys[ii], method, 1) &&
26886978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		keyMatchesMethod(filter->filterKeys[ii], method, 0)) {
26896978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        // Add remTime(s)
26906978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        // TODO: think about how we should add remTimes.. should we add remTime to threads
26916978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        // that were waiting or being waited on? for now, keep it simple and just add the
26926978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        // execution time to the current thread.
26936978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        filter->times.threadExecutionTimes[threadId] += remTime;
26946978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		addedRemTime = 1;
26956978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    }
26966978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	}
26976978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    }
26986978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
26996978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    return addedExecutionTime | (addedRemTime << 1);
27006978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince}
27016978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
27026978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipincevoid dumpFilters(Filter** filters) {
27036978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int i;
27046978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    for (i = 0; i < numFilters; i++) {
27056978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        int j;
27066978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	fprintf(stderr, "FILTER %s\n", filters[i]->filterName);
27076978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	for (j = 0; j < filters[i]->numKeys; j++) {
27086978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    fprintf(stderr, "Keys: %s, type %d", filters[i]->filterKeys[j].keys[0],
27096978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    filters[i]->filterKeys[j].type[0]);
27106978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    if (filters[i]->filterKeys[j].keys[1] != NULL) {
27116978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        fprintf(stderr, " AND %s, type %d", filters[i]->filterKeys[j].keys[1],
27126978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince			filters[i]->filterKeys[j].type[1]);
27136978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    }
27146978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    fprintf(stderr, "; flags: %d\n", filters[i]->filterKeys[j].flags);
27156978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	}
27166978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    }
27176978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince}
27186978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
27196978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince/*
27206978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * See parseFilters for required data format.
27216978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * 'data' must point to the beginning of a filter definition.
27226978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince */
27236978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipincechar* parseFilter(char* data, char* dataEnd, Filter** filters, int num) {
27246978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
27256978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    Filter* filter;
27266978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int next, count, i;
27276978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int tmpOffset, tmpKeyLen;
27286978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    char* tmpKey;
27296978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    char* key1;
27306978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    char* key2;
27316978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
27326978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    filter = (Filter*) malloc(sizeof(Filter));
27336978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    filter->activeCount = 0;
27346978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    filter->activeThreads = (int*) calloc(DEFAULT_ACTIVE_THREADS, sizeof(int));
27356978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    filter->activationKeys = (int*) calloc(DEFAULT_ACTIVE_THREADS, sizeof(int));
27366978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
27376978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    next = findNextChar(data + 1, dataEnd - data - 1, '\n');
27386978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    if (next < 0) {
27396978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        // TODO: what should we do here?
27406978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        // End of file reached...
27416978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    }
27426978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    data[next+1] = '\0';
27436978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    filter->filterName = data + 1;
27446978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    data += next + 2; // Careful
27456978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
27466978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    /*
27476978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince     * Count the number of keys (one per line).
27486978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince     */
27496978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    count = countLinesToChar(data, dataEnd - data, FILTER_TAG);
27506978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    if (count <= 0) {
27516978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        fprintf(stderr,
27526978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		"ERROR: failed while parsing filter %s (found %d keys)\n",
27536978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		filter->filterName, count);
27546978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	return NULL; // TODO: Should do something else
27556978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	// Could return filter with 0 keys instead (probably better to avoid random segfaults)
27566978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    }
27576978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
27586978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    filter->filterKeys = (FilterKey*) malloc(sizeof(FilterKey) * count);
27596978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
27606978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    /*
27616978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince     * Extract all entries.
27626978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince     */
27636978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    tmpOffset = 0;
27646978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    for (i = 0; i < count; i++) {
27656978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        next = findNextChar(data, dataEnd - data, '\n');
27666978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	//        assert(next > 0); // TODO: revise... (skip if next == 0 ?)
27676978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        data[next] = '\0';
27686978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	tmpKey = data;
27696978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
27706978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        if (*data == FILTER_FLAG_THREAD) {
27716978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince            filter->filterKeys[i].flags = 1;
27726978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince            tmpKey++;
27736978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	} else {
27746978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince            filter->filterKeys[i].flags = 0;
27756978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	}
27766978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
27776978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	tmpOffset = findNextChar(tmpKey, next, ',');
27786978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
27796978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        if (tmpOffset < 0) {
27806978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince            // No comma, so only 1 key
27816978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince            key1 = tmpKey;
27826978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    key2 = tmpKey;
27836978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
27846978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    // Get type for key1
27856978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince            filter->filterKeys[i].type[0] = FILTER_TYPE_CLASS; // default
27866978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince            tmpOffset = findNextChar(key1, next, '(');
27876978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    if (tmpOffset > 0) {
27886978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        if (findNextChar(key1, next, ')') == tmpOffset + 1) {
27896978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    filter->filterKeys[i].type[0] = FILTER_TYPE_METHOD;
27906978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    filter->filterKeys[i].type[1] = FILTER_TYPE_METHOD;
27916978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		}
27926978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		key1[tmpOffset] = '\0';
27936978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    }
27946978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	} else {
27956978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    // Pair of keys
27966978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    tmpKey[tmpOffset] = '\0';
27976978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    key1 = tmpKey;
27986978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    key2 = tmpKey + tmpOffset + 1;
27996978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
28006978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    // Get type for key1
28016978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    filter->filterKeys[i].type[0] = FILTER_TYPE_CLASS;
28026978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    tmpKeyLen = tmpOffset;
28036978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince            tmpOffset = findNextChar(key1, tmpKeyLen, '(');
28046978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    if (tmpOffset > 0) {
28056978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        if (findNextChar(key1, tmpKeyLen, ')') == tmpOffset + 1) {
28066978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    filter->filterKeys[i].type[0] = FILTER_TYPE_METHOD;
28076978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		}
28086978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		key1[tmpOffset] = '\0';
28096978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    }
28106978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
28116978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    // Get type for key2
28126978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    filter->filterKeys[i].type[1] = FILTER_TYPE_CLASS;
28136978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince            tmpOffset = findNextChar(key2, next - tmpKeyLen, '(');
28146978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    if (tmpOffset > 0) {
28156978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        if (findNextChar(key2, next - tmpKeyLen, ')') == tmpOffset + 1) {
28166978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    filter->filterKeys[i].type[1] = FILTER_TYPE_METHOD;
28176978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		}
28186978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		key2[tmpOffset] = '\0';
28196978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    }
28206978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	}
28216978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
28226978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	filter->filterKeys[i].keys[0] = key1;
28236978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	filter->filterKeys[i].keys[1] = key2;
28246978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        data += next+1;
28256978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    }
28266978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
28276978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    filter->numKeys = count;
28286978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    filters[num] = filter;
28296978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
28306978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    return data;
28316978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince}
28326978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
28336978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince/*
28346978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * Parses filters from given file. The file must follow the following format:
28356978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince *
28366978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * *FilterName    <- creates a new filter with keys to follow
28376978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * A.method()     <- key that triggers whenever A.method() enters/exit
28386978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * Class          <- key that triggers whenever any method from Class enters/exits
28396978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * +CrossThread   <- same as above, but keeps track of execution times accross threads
28406978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * B.m(),C.m()    <- key that triggers filter on when B.m() enters and off when C.m() exits
28416978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince *
28426978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince * TODO: add concrete example to make things clear
28436978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince */
28446978d9dd28968b3817533d036ae7b53309053faaRodrigo IpinceFilter** parseFilters(const char* filterFileName) {
28456978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
28466978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    Filter** filters = NULL;
28476978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    FILE* fp = NULL;
28486978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    long len;
28496978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    char* data;
28506978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    char* dataEnd;
28516978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    char* dataStart;
28526978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int i, next, count;
28536978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
28546978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    fp = fopen(filterFileName, "r");
28556978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    if (fp == NULL)
28566978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        goto bail;
28576978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
28586978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    if (fseek(fp, 0L, SEEK_END) != 0) {
28596978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        perror("fseek");
28606978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        goto bail;
28616978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    }
28626978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
28636978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    len = ftell(fp);
28646978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    if (len == 0) {
28656978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        fprintf(stderr, "WARNING: Filter file is empty.\n");
28666978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        goto bail;
28676978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    }
28686978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    rewind(fp);
28696978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
28706978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    data = (char*) malloc(len);
28716978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    if (data == NULL) {
28726978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        fprintf(stderr, "ERROR: unable to alloc %ld bytes for filter file\n", len);
28736978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        goto bail;
28746978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    }
28756978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
28766978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    // Read file into memory
28776978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    if (fread(data, 1, len, fp) != (size_t) len) {
28786978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        fprintf(stderr, "ERROR: unable to read %ld bytes from filter file\n", len);
28796978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        goto bail;
28806978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    }
28816978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
28826978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    dataStart = data;
28836978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    dataEnd = data + len;
28846978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
28856978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    // Figure out how many filters there are
28866978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    numFilters = 0;
28876978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    next = -1;
28886978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
28896978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    while (1) {
28906978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        if (*data == FILTER_TAG)
28916978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    numFilters++;
28926978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        next = findNextChar(data, len, '\n');
28936978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        if (next < 0)
28946978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince            break;
28956978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        data += next+1;
28966978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        len -= next+1;
28976978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    }
28986978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
28996978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    if (numFilters == 0) {
29006978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        fprintf(stderr, "WARNING: no filters found. Continuing without filters\n");
29016978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        goto bail;
29026978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    }
29036978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
29046978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    filters = (Filter**) calloc(numFilters, sizeof(Filter *));
29056978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    if (filters == NULL) {
29066978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        fprintf(stderr, "ERROR: unable to alloc memory for filters");
29076978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        goto bail;
29086978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    }
29096978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
29106978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    data = dataStart;
29116978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    for (i = 0; i < numFilters; i++) {
29126978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        data = parseFilter(data, dataEnd, filters, i);
29136978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    }
29146978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
29156978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    return filters;
29166978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
29176978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipincebail:
29186978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    if (fp != NULL)
29196978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        fclose(fp);
29206978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
29216978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    return NULL;
29226978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
29236978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince}
29246978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
29256978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
29266978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince/*
2927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Read the key and data files and return the MethodEntries for those files
2928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
29296978d9dd28968b3817533d036ae7b53309053faaRodrigo IpinceDataKeys* parseDataKeys(TraceData* traceData, const char* traceFileName,
29306978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince			uint64_t* threadTime, Filter** filters)
2931de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro{
2932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DataKeys* dataKeys = NULL;
2933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry **pMethods = NULL;
2934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry* method;
2935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    FILE* dataFp = NULL;
2936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DataHeader dataHeader;
29376978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    int ii, jj, numThreads;
2938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t currentTime;
2939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry* caller;
2940de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dataFp = fopen(traceFileName, "r");
2942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dataFp == NULL)
2943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((dataKeys = parseKeys(dataFp, 0)) == NULL)
29466978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince       goto bail;
2947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (parseDataHeader(dataFp, &dataHeader) < 0)
2949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
29516978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    numThreads = dataKeys->numThreads;
29526978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
2953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
2954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    FILE *dumpStream = fopen("debug", "w");
2955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
2956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (1) {
2957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int threadId;
2958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int methodVal;
2959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int action;
2960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int methodId;
2961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        CallStack *pStack;
29626978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
2963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
2964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Extract values from file.
2965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (readDataRecord(dataFp, &threadId, &methodVal, &currentTime))
2967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
29686978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
2969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        action = METHOD_ACTION(methodVal);
2970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodId = METHOD_ID(methodVal);
2971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Get the call stack for this thread */
2973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pStack = traceData->stacks[threadId];
2974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* If there is no call stack yet for this thread, then allocate one */
2976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pStack == NULL) {
2977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pStack = malloc(sizeof(CallStack));
2978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pStack->top = 0;
2979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pStack->lastEventTime = currentTime;
2980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pStack->threadStartTime = currentTime;
29816978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    pStack->remTimes = (uint64_t*) calloc(numFilters, sizeof(uint64_t));
2982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            traceData->stacks[threadId] = pStack;
2983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Lookup the current method */
2986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        method = lookupMethod(dataKeys, methodId);
2987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method == NULL)
2988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method = &dataKeys->methods[UNKNOWN_INDEX];
2989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
2991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method->methodName) {
29926978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    fprintf(dumpStream, "%2d %-8llu %d %8llu r %d c %d %s.%s %s\n",
29936978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	           threadId, currentTime, action, pStack->threadStartTime,
29946978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	           method->recursiveEntries,
29956978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	           pStack->top, method->className, method->methodName,
29966978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	           method->signature);
2997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
29986978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    printf(dumpStream, "%2d %-8llu %d %8llu r %d c %d %s\n",
29996978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	           threadId, currentTime, action, pStack->threadStartTime,
30006978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	           method->recursiveEntries,
30016978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	           pStack->top, method->className);
3002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
3004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (action == METHOD_TRACE_ENTER) {
3006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* This is a method entry */
3007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (pStack->top >= MAX_STACK_DEPTH) {
3008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                fprintf(stderr, "Stack overflow (exceeded %d frames)\n",
3009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        MAX_STACK_DEPTH);
3010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                exit(1);
3011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Get the caller method */
3014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (pStack->top >= 1)
3015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                caller = pStack->calls[pStack->top - 1].method;
3016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            else
3017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                caller = &dataKeys->methods[TOPLEVEL_INDEX];
3018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            countRecursiveEntries(pStack, pStack->top, caller);
3019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            caller->elapsedExclusive += currentTime - pStack->lastEventTime;
3020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
3021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (caller->elapsedExclusive > 10000000)
3022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                fprintf(dumpStream, "%llu current %llu last %llu diff %llu\n",
3023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        caller->elapsedExclusive, currentTime,
3024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        pStack->lastEventTime,
3025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        currentTime - pStack->lastEventTime);
3026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
3027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (caller->recursiveEntries <= 1) {
3028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                caller->topExclusive += currentTime - pStack->lastEventTime;
3029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Push the method on the stack for this thread */
3032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pStack->calls[pStack->top].method = method;
3033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pStack->calls[pStack->top++].entryTime = currentTime;
30346978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
30356978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    // For each filter
30366978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    int result = 0;
30376978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    for (ii = 0; ii < numFilters; ii++) {
30386978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        result = filterMethod(method, filters[ii], 1, threadId, numThreads,
30396978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince				       currentTime - pStack->lastEventTime, pStack->remTimes[ii]);
30406978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
30416978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		// TODO: make remTimes work properly
30426978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		// Consider moving remTimes handling together with the rest
30436978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		// of time handling and clean up the return codes
30446978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		/*
30456978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		if (result == 0) { // no time added, no remTime added
30466978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    pStack->remTimes[ii] += currentTime - pStack->lastEventTime;
30476978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		} else if (result == 3 || result == 4) { // remTime added
30486978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    // Reset remTime, since it's been added
30496978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    pStack->remTimes[ii] = 0;
30506978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		}
30516978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		*/
30526978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    }
30536978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
3054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* This is a method exit */
3056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            uint64_t entryTime = 0;
3057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Pop the method off the stack for this thread */
3059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (pStack->top > 0) {
3060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pStack->top -= 1;
3061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                entryTime = pStack->calls[pStack->top].entryTime;
3062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (method != pStack->calls[pStack->top].method) {
3063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (method->methodName) {
3064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        fprintf(stderr,
3065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            "Exit from method %s.%s %s does not match stack:\n",
3066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            method->className, method->methodName,
3067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            method->signature);
3068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } else {
3069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        fprintf(stderr,
3070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            "Exit from method %s does not match stack:\n",
3071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            method->className);
3072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    stackDump(pStack, pStack->top + 1);
3074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    exit(1);
3075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Get the caller method */
3079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (pStack->top >= 1)
3080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                caller = pStack->calls[pStack->top - 1].method;
3081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            else
3082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                caller = &dataKeys->methods[TOPLEVEL_INDEX];
3083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            countRecursiveEntries(pStack, pStack->top, caller);
3084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            countRecursiveEntries(pStack, pStack->top, method);
3085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            uint64_t elapsed = currentTime - entryTime;
3086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            addInclusiveTime(caller, method, elapsed);
3087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->elapsedExclusive += currentTime - pStack->lastEventTime;
3088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (method->recursiveEntries == 0) {
3089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                method->topExclusive += currentTime - pStack->lastEventTime;
3090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
30916978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
30926978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    // For each filter
30936978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    int result = 0;
30946978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    for (ii = 0; ii < numFilters; ii++) {
30956978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        result = filterMethod(method, filters[ii], 0, threadId, numThreads,
30966978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince				       currentTime - pStack->lastEventTime, pStack->remTimes[ii]);
30976978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
30986978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		// TODO: make remTimes work properly
30996978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		/*
31006978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		if (result == 0) { // no time added, no remTime added
31016978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    pStack->remTimes[ii] += currentTime - pStack->lastEventTime;
31026978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		} else if (result == 3 || result == 4) { // remTime added
31036978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    // Reset remTime, since it's been added
31046978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    pStack->remTimes[ii] = 0;
31056978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		}
31066978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		*/
31076978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    }
31086978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
3109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Remember the time of the last entry or exit event */
3111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pStack->lastEventTime = currentTime;
3112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If we have calls on the stack when the trace ends, then clean
3115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * up the stack and add time to the callers by pretending that we
3116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * are exiting from their methods now.
3117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStack *pStack;
3119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int threadId;
31205b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    uint64_t elapsedTime = 0;
3121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t sumThreadTime = 0;
3122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (threadId = 0; threadId < MAX_THREADS; ++threadId) {
31235b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
3124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pStack = traceData->stacks[threadId];
3125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* If this thread never existed, then continue with next thread */
3127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pStack == NULL)
3128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
3129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
31306978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        /* Calculate times spent in thread, and add it to total time */
31315b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        elapsedTime = pStack->lastEventTime - pStack->threadStartTime;
31325b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        sumThreadTime += elapsedTime;
31335b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
3134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (ii = 0; ii < pStack->top; ++ii) {
31356978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	  //printf("in loop\n");
31366978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
3137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (ii == 0)
3138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                caller = &dataKeys->methods[TOPLEVEL_INDEX];
3139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            else
3140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                caller = pStack->calls[ii - 1].method;
3141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method = pStack->calls[ii].method;
3142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            countRecursiveEntries(pStack, ii, caller);
3143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            countRecursiveEntries(pStack, ii, method);
3144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            uint64_t entryTime = pStack->calls[ii].entryTime;
3146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            uint64_t elapsed = pStack->lastEventTime - entryTime;
3147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            addInclusiveTime(caller, method, elapsed);
31486978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
31496978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    // For each filter
31506978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    int result = 0;
31516978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    for (ii = 0; ii < numFilters; ii++) {
31526978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        result = filterMethod(method, filters[ii], 0, threadId, numThreads,
31536978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince				       currentTime - pStack->lastEventTime, pStack->remTimes[ii]);
31546978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
31556978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		// TODO: make remTimes work properly
31566978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		/*
31576978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		if (result == 0) { // no time added, no remTime added
31586978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    pStack->remTimes[ii] += currentTime - pStack->lastEventTime;
31596978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		} else if (result == 3 || result == 4) { // remTime added
31606978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    // Reset remTime, since it's been added
31616978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		    pStack->remTimes[ii] = 0;
31626978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		}
31636978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince		*/
31646978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    }
3165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
31666978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
31676978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	/* Save the per-thread elapsed time in the DataKeys struct */
31686978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	for (ii = 0; ii < dataKeys->numThreads; ++ii) {
31696978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    if (dataKeys->threads[ii].threadId == threadId) {
31706978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince                dataKeys->threads[ii].elapsedTime = elapsedTime;
31716978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	    }
31726978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	}
31736978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
31746978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
3175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    caller = &dataKeys->methods[TOPLEVEL_INDEX];
3177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    caller->elapsedInclusive = sumThreadTime;
3178de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
3180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fclose(dumpStream);
3181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
3182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (threadTime != NULL) {
3184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *threadTime = sumThreadTime;
3185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
3188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dataFp != NULL)
3189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fclose(dataFp);
3190de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dataKeys;
3192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectMethodEntry** parseMethodEntries(DataKeys* dataKeys)
3195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii;
3197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Create a new array of pointers to the methods and sort the pointers
3198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * instead of the actual MethodEntry structs.  We need to do this
3199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * because there are other lists that contain pointers to the
3200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * MethodEntry structs.
3201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry** pMethods = (MethodEntry**) malloc(sizeof(MethodEntry*) * dataKeys->numMethods);
3203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < dataKeys->numMethods; ++ii) {
3204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        MethodEntry* entry = &dataKeys->methods[ii];
3205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pMethods[ii] = entry;
3206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3207de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return pMethods;
3209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
32116978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
3212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Produce a function profile from the following methods
3214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
32155b55af706cf3823494123da092a0a0319297a93eRodrigo Ipincevoid profileTrace(TraceData* traceData, MethodEntry **pMethods, int numMethods, uint64_t sumThreadTime,
32166978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince                  ThreadEntry *pThreads, int numThreads, Filter** filters)
3217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
32186978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince   /* Print the html header, if necessary */
3219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
3220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(htmlHeader, gOptions.sortableUrl);
3221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        outputTableOfContents();
3222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printExclusiveProfile(pMethods, numMethods, sumThreadTime);
3225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printInclusiveProfile(pMethods, numMethods, sumThreadTime);
3226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
32276978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    printThreadProfile(pThreads, numThreads, sumThreadTime, filters);
32285b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
3229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    createClassList(traceData, pMethods, numMethods);
3230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printClassProfiles(traceData, sumThreadTime);
3231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    createUniqueMethodList(traceData, pMethods, numMethods);
3233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printMethodProfiles(traceData, sumThreadTime);
3234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
3236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%s", htmlFooter);
3237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint compareMethodNamesForDiff(const void *a, const void *b)
3241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
3243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const MethodEntry *methodA = *(const MethodEntry**)a;
3245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const MethodEntry *methodB = *(const MethodEntry**)b;
3246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (methodA->methodName == NULL || methodB->methodName == NULL) {
3247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return compareClassNames(a, b);
3248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = strcmp(methodA->methodName, methodB->methodName);
3250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result == 0) {
3251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = strcmp(methodA->signature, methodB->signature);
3252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result == 0) {
3253de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro           return strcmp(methodA->className, methodB->className);
3254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
3257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint findMatch(MethodEntry** methods, int size, MethodEntry* matchThis)
3260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
3262de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0 ; i < size ; i++) {
3264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        MethodEntry* method = methods[i];
3265de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method != NULL && !compareMethodNamesForDiff(&method, &matchThis)) {
3267de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro//            printf("%s.%s == %s.%s<br>\n", matchThis->className, matchThis->methodName,
3268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project  //              method->className, method->methodName);
3269de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return i;
3271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*            if (!compareMethodNames(&method, &matchThis)) {
3272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return i;
3273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/        }
3275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3276de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return -1;
3278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint compareDiffEntriesExculsive(const void *a, const void *b)
3281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
3283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DiffEntry* entryA = (const DiffEntry*)a;
3285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DiffEntry* entryB = (const DiffEntry*)b;
3286de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (entryA->differenceExclusive < entryB->differenceExclusive) {
3288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
3289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else if (entryA->differenceExclusive > entryB->differenceExclusive) {
3290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
3291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3292de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
3294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint compareDiffEntriesInculsive(const void *a, const void *b)
3297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
3299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DiffEntry* entryA = (const DiffEntry*)a;
3301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DiffEntry* entryB = (const DiffEntry*)b;
3302de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (entryA->differenceInclusive < entryB->differenceInclusive) {
3304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
3305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else if (entryA->differenceInclusive > entryB->differenceInclusive) {
3306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
3307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3308de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
3310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3312de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapirovoid printMissingMethod(MethodEntry* method)
3313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char classBuf[HTML_BUFSIZE];
3315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char methodBuf[HTML_BUFSIZE];
3316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* className;
3317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* methodName;
3318de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    className = htmlEscape(method->className, classBuf, HTML_BUFSIZE);
3320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    methodName = htmlEscape(method->methodName, methodBuf, HTML_BUFSIZE);
3321de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3322de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro    if (gOptions.outputHtml) printf("<tr><td>\n");
3323de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("%s.%s ", className, methodName);
3325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) printf("</td><td>");
3326de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("%lld ", method->elapsedExclusive);
3328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) printf("</td><td>");
3329de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("%lld ", method->elapsedInclusive);
3331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) printf("</td><td>");
3332de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("%d\n", method->numCalls[0]);
3334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) printf("</td><td>\n");
3335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid createDiff(DataKeys* d1, uint64_t sum1, DataKeys* d2, uint64_t sum2)
3339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry** methods1 = parseMethodEntries(d1);
3341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry** methods2 = parseMethodEntries(d2);
3342de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3343de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro    // sort and assign the indicies
3344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
3345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(methods1, d1->numMethods, sizeof(MethodEntry*), compareElapsedInclusive);
3346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < d1->numMethods; ++i) {
3347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methods1[i]->index = i;
3348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(methods2, d2->numMethods, sizeof(MethodEntry*), compareElapsedInclusive);
3351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < d2->numMethods; ++i) {
3352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methods2[i]->index = i;
3353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3354de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int max = (d1->numMethods < d2->numMethods) ? d2->numMethods : d1->numMethods;
3356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    max++;
3357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DiffEntry* diffs = (DiffEntry*)malloc(max * sizeof(DiffEntry));
3358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(diffs, 0, max * sizeof(DiffEntry));
3359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DiffEntry* ptr = diffs;
3360de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//    printf("<br>d1->numMethods: %d d1->numMethods: %d<br>\n", d1->numMethods, d2->numMethods);
3362de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int matches = 0;
3364de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0 ; i < d1->numMethods ; i++) {
3366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int match = findMatch(methods2, d2->numMethods, methods1[i]);
3367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (match >= 0) {
3368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ptr->method1 = methods1[i];
3369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ptr->method2 = methods2[match];
3370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            uint64_t e1 = ptr->method1->elapsedExclusive;
3372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            uint64_t e2 = ptr->method2->elapsedExclusive;
3373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (e1 > 0) {
3374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ptr->differenceExclusive = e2 - e1;
3375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ptr->differenceExclusivePercentage = ((double)e2 / (double)e1) * 100.0;
3376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            uint64_t i1 = ptr->method1->elapsedInclusive;
3379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            uint64_t i2 = ptr->method2->elapsedInclusive;
3380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (i1 > 0) {
3381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ptr->differenceInclusive = i2 - i1;
3382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ptr->differenceInclusivePercentage = ((double)i2 / (double)i1) * 100.0;
3383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3384de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // clear these out so we don't find them again and we know which ones
3386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // we have left over
3387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methods1[i] = NULL;
3388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methods2[match] = NULL;
3389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ptr++;
3390de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            matches++;
3392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ptr->method1 = NULL;
3395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ptr->method2 = NULL;
3396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(diffs, matches, sizeof(DiffEntry), compareDiffEntriesExculsive);
3398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ptr = diffs;
3399de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
3401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(htmlHeader, gOptions.sortableUrl);
3402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<h3>Table of Contents</h3>\n");
3403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<ul>\n");
3404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<li><a href='#exclusive'>Exclusive</a>\n");
3405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<li><a href='#inclusive'>Inclusive</a>\n");
3406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("</ul>\n");
3407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("Run 1: %s<br>\n", gOptions.diffFileName);
3408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("Run 2: %s<br>\n", gOptions.traceFileName);
3409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<a name=\"exclusive\"></a><h3 id=\"exclusive\">Exclusive</h3>\n");
3410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(tableHeader, "exclusive_table");
3411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3412de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char classBuf[HTML_BUFSIZE];
3414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char methodBuf[HTML_BUFSIZE];
3415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* className;
3416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* methodName;
3417de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (ptr->method1 != NULL && ptr->method2 != NULL) {
3419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("<tr><td>\n");
3420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        className = htmlEscape(ptr->method1->className, classBuf, HTML_BUFSIZE);
3422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodName = htmlEscape(ptr->method1->methodName, methodBuf, HTML_BUFSIZE);
3423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%s.%s ", className, methodName);
3425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>");
3426de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%lld ", ptr->method1->elapsedExclusive);
3428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>");
3429de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%llu ", ptr->method2->elapsedExclusive);
3431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>");
3432de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%lld ", ptr->differenceExclusive);
3434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>");
3435de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%.2f\n", ptr->differenceExclusivePercentage);
3437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>\n");
3438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%d\n", ptr->method1->numCalls[0]);
3440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>\n");
3441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%d\n", ptr->method2->numCalls[0]);
3443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td></tr>\n");
3444de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ptr++;
3446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3447de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) printf("</table>\n");
3449de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
3451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(htmlHeader, gOptions.sortableUrl);
3452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("Run 1: %s<br>\n", gOptions.diffFileName);
3453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("Run 2: %s<br>\n", gOptions.traceFileName);
3454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<a name=\"inclusive\"></a><h3 id=\"inculisve\">Inclusive</h3>\n");
3455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(tableHeader, "inclusive_table");
3456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3457de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(diffs, matches, sizeof(DiffEntry), compareDiffEntriesInculsive);
3459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ptr = diffs;
3460de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (ptr->method1 != NULL && ptr->method2 != NULL) {
3462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("<tr><td>\n");
3463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        className = htmlEscape(ptr->method1->className, classBuf, HTML_BUFSIZE);
3465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodName = htmlEscape(ptr->method1->methodName, methodBuf, HTML_BUFSIZE);
3466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%s.%s ", className, methodName);
3468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>");
3469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%lld ", ptr->method1->elapsedInclusive);
3471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>");
3472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%llu ", ptr->method2->elapsedInclusive);
3474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>");
3475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%lld ", ptr->differenceInclusive);
3477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>");
3478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%.2f\n", ptr->differenceInclusivePercentage);
3480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>\n");
3481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%d\n", ptr->method1->numCalls[0]);
3483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>\n");
3484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%d\n", ptr->method2->numCalls[0]);
3486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td></tr>\n");
3487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ptr++;
3489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
3492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("</table>\n");
3493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<h3>Run 1 methods not found in Run 2</h3>");
3494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(tableHeaderMissing);
3495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3496de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < d1->numMethods; ++i) {
3498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methods1[i] != NULL) {
3499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project           printMissingMethod(methods1[i]);
3500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3502de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
3504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("</table>\n");
3505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<h3>Run 2 methods not found in Run 1</h3>");
3506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(tableHeaderMissing);
3507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3508de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < d2->numMethods; ++i) {
3510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methods2[i] != NULL) {
3511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printMissingMethod(methods2[i]);
3512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3514de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) printf("</body></html\n");
3516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint usage(const char *program)
3519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
35206978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    fprintf(stderr, "usage: %s [-ho] [-s sortable] [-d trace-file-name] [-g outfile] [-f filter-file] trace-file-name\n", program);
3521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, "  -d trace-file-name  - Diff with this trace\n");
3522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, "  -g outfile          - Write graph to 'outfile'\n");
35236978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    fprintf(stderr, "  -f filter-file      - Filter functions as specified in file\n");
3524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, "  -k                  - When writing a graph, keep the intermediate DOT file\n");
3525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, "  -h                  - Turn on HTML output\n");
3526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, "  -o                  - Dump the dmtrace file instead of profiling\n");
3527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, "  -s                  - URL base to where the sortable javascript file\n");
3528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, "  -t threshold        - Threshold percentage for including nodes in the graph\n");
3529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 2;
3530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// Returns true if there was an error
3533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint parseOptions(int argc, char **argv)
3534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (1) {
35366978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        int opt = getopt(argc, argv, "d:hg:kos:t:f:");
3537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (opt == -1)
3538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
3539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (opt) {
3540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'd':
3541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                gOptions.diffFileName = optarg;
3542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'g':
3544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                gOptions.graphFileName = optarg;
3545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
35466978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince            case 'f':
35476978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince	        gOptions.filterFileName = optarg;
354844828ed25841ea5180346695dfc07ef33b2b7e73Jack Veenstra                break;
3549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'k':
3550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                gOptions.keepDotFile = 1;
3551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'h':
3553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                gOptions.outputHtml = 1;
3554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'o':
3556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                gOptions.dump = 1;
3557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 's':
3559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                gOptions.sortableUrl = optarg;
3560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 't':
3562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                gOptions.threshold = atoi(optarg);
3563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default:
3565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return 1;
3566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
3569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parse args.
3573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint main(int argc, char** argv)
3575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
35766978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
3577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gOptions.threshold = -1;
35786978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
3579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // Parse the options
3580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (parseOptions(argc, argv) || argc - optind != 1)
3581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return usage(argv[0]);
3582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gOptions.traceFileName = argv[optind];
3584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.threshold < 0 || 100 <= gOptions.threshold) {
3586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gOptions.threshold = 20;
3587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
35885b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
3589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.dump) {
3590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dumpTrace();
3591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 0;
3592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t sumThreadTime = 0;
35956978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
35966978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    Filter** filters = NULL;
35976978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    if (gOptions.filterFileName != NULL) {
35986978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        filters = parseFilters(gOptions.filterFileName);
35996978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince    }
36006978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
3601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    TraceData data1;
3602fe1d6d586614fa51d82857e09128d6671be21d56Andy McFadden    memset(&data1, 0, sizeof(data1));
3603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DataKeys* dataKeys = parseDataKeys(&data1, gOptions.traceFileName,
36046978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince                                       &sumThreadTime, filters);
3605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dataKeys == NULL) {
3606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr, "Cannot read trace.\n");
3607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        exit(1);
3608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.diffFileName != NULL) {
3611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        uint64_t sum2;
3612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        TraceData data2;
36136978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince        DataKeys* d2 = parseDataKeys(&data2, gOptions.diffFileName, &sum2, filters);
3614de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        createDiff(d2, sum2, dataKeys, sumThreadTime);
3616de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        freeDataKeys(d2);
3618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
3619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        MethodEntry** methods = parseMethodEntries(dataKeys);
36205b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince        profileTrace(&data1, methods, dataKeys->numMethods, sumThreadTime,
36216978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince                     dataKeys->threads, dataKeys->numThreads, filters);
3622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.graphFileName != NULL) {
3623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            createInclusiveProfileGraphNew(dataKeys);
3624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(methods);
3626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3627de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    freeDataKeys(dataKeys);
3629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
3631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3632