17b522639a499f63ccb5162576830d0c20539bd05Andy McFadden/*
27b522639a499f63ccb5162576830d0c20539bd05Andy McFadden * Copyright (C) 2006 The Android Open Source Project
37b522639a499f63ccb5162576830d0c20539bd05Andy McFadden *
47b522639a499f63ccb5162576830d0c20539bd05Andy McFadden * Licensed under the Apache License, Version 2.0 (the "License");
57b522639a499f63ccb5162576830d0c20539bd05Andy McFadden * you may not use this file except in compliance with the License.
67b522639a499f63ccb5162576830d0c20539bd05Andy McFadden * You may obtain a copy of the License at
77b522639a499f63ccb5162576830d0c20539bd05Andy McFadden *
87b522639a499f63ccb5162576830d0c20539bd05Andy McFadden *      http://www.apache.org/licenses/LICENSE-2.0
97b522639a499f63ccb5162576830d0c20539bd05Andy McFadden *
107b522639a499f63ccb5162576830d0c20539bd05Andy McFadden * Unless required by applicable law or agreed to in writing, software
117b522639a499f63ccb5162576830d0c20539bd05Andy McFadden * distributed under the License is distributed on an "AS IS" BASIS,
127b522639a499f63ccb5162576830d0c20539bd05Andy McFadden * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137b522639a499f63ccb5162576830d0c20539bd05Andy McFadden * See the License for the specific language governing permissions and
147b522639a499f63ccb5162576830d0c20539bd05Andy McFadden * limitations under the License.
157b522639a499f63ccb5162576830d0c20539bd05Andy McFadden */
165b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Process dmtrace output.
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is the wrong way to go about it -- C is a clumsy language for
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * shuffling data around.  It'll do for a first pass.
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define NOT_VM
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Profile.h"        // from VM header
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdio.h>
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <string.h>
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <unistd.h>
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <inttypes.h>
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <time.h>
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h>
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <assert.h>
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
35949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown/* Version number in the key file.
36949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown * Version 1 uses one byte for the thread id.
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Version 2 uses two bytes for the thread ids.
38949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown * Version 3 encodes the record size and adds an optional extra timestamp field.
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint versionNumber;
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* arbitrarily limit indentation */
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define MAX_STACK_DEPTH 10000
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* thread list in key file is not reliable, so just max out */
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define MAX_THREADS     32768
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Size of temporary buffers for escaping html strings */
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define HTML_BUFSIZE 10240
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
51de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapirochar *htmlHeader =
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"<html>\n<head>\n<script type=\"text/javascript\" src=\"%ssortable.js\"></script>\n"
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"<script langugage=\"javascript\">\n"
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"function toggle(item) {\n"
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"    obj=document.getElementById(item);\n"
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"    visible=(obj.style.display!=\"none\" && obj.style.display!=\"\");\n"
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"    key=document.getElementById(\"x\" + item);\n"
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"    if (visible) {\n"
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"        obj.style.display=\"none\";\n"
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"        key.innerHTML=\"+\";\n"
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"    } else {\n"
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"        obj.style.display=\"block\";\n"
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"        key.innerHTML=\"-\";\n"
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"    }\n"
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"}\n"
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"function onMouseOver(obj) {\n"
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"    obj.style.background=\"lightblue\";\n"
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"}\n"
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"function onMouseOut(obj) {\n"
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"    obj.style.background=\"white\";\n"
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"}\n"
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"</script>\n"
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"<style type=\"text/css\">\n"
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"div { font-family: courier; font-size: 13 }\n"
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"div.parent { margin-left: 15; display: none }\n"
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"div.leaf { margin-left: 10 }\n"
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"div.header { margin-left: 10 }\n"
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"div.link { margin-left: 10; cursor: move }\n"
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"span.parent { padding-right: 10; }\n"
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"span.leaf { padding-right: 10; }\n"
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"a img { border: 0;}\n"
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"table.sortable th { border-width: 0px 1px 1px 1px; background-color: #ccc;}\n"
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"a { text-decoration: none; }\n"
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"a:hover { text-decoration: underline; }\n"
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"table.sortable th, table.sortable td { text-align: left;}"
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"table.sortable tr.odd td { background-color: #ddd; }\n"
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"table.sortable tr.even td { background-color: #fff; }\n"
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"</style>\n"
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"</head><body>\n\n";
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchar *htmlFooter = "\n</body>\n</html>\n";
92de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapirochar *profileSeparator =
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "======================================================================";
94de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
95de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiroconst char* tableHeader =
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<table class='sortable' id='%s'><tr>\n"
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th>Method</th>\n"
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th>Run 1 (us)</th>\n"
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th>Run 2 (us)</th>\n"
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th>Diff (us)</th>\n"
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th>Diff (%%)</th>\n"
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th>1: # calls</th>\n"
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th>2: # calls</th>\n"
104de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro    "</tr>\n";
105de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
106de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiroconst char* tableHeaderMissing =
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<table class='sortable' id='%s'>\n"
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th>Method</th>\n"
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th>Exclusive</th>\n"
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th>Inclusive</th>\n"
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<th># calls</th>\n";
112de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
113de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro#define GRAPH_LABEL_VISITED 0x0001
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define GRAPH_NODE_VISITED  0x0002
115de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Values from the header of the data file.
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct DataHeader {
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned int magic;
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    short version;
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    short offsetToData;
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    long long startWhen;
124949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown    short recordSize;
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} DataHeader;
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Entry from the thread list.
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct ThreadEntry {
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int         threadId;
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* threadName;
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} ThreadEntry;
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstruct MethodEntry;
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct TimedMethod {
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct TimedMethod *next;
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t elapsedInclusive;
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numCalls;
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct MethodEntry *method;
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} TimedMethod;
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct ClassEntry {
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char *className;
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t elapsedExclusive;
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numMethods;
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct MethodEntry **methods;       /* list of methods in this class */
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numCalls[2];                    /* 0=normal, 1=recursive */
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} ClassEntry;
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct UniqueMethodEntry {
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t elapsedExclusive;
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numMethods;
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct MethodEntry **methods;       /* list of methods with same name */
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numCalls[2];                    /* 0=normal, 1=recursive */
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} UniqueMethodEntry;
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Entry from the method list.
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct MethodEntry {
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned int methodId;
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* className;
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* methodName;
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* signature;
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* fileName;
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int lineNum;
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t elapsedExclusive;
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t elapsedInclusive;
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t topExclusive;              /* non-recursive exclusive time */
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t recursiveInclusive;
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct TimedMethod *parents[2];     /* 0=normal, 1=recursive */
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct TimedMethod *children[2];    /* 0=normal, 1=recursive */
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numCalls[2];                    /* 0=normal, 1=recursive */
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int index;                  /* used after sorting to number methods */
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int recursiveEntries;       /* number of entries on the stack */
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int graphState;             /* used when graphing to see if this method has been visited before */
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} MethodEntry;
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The parsed contents of the key file.
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct DataKeys {
1845b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince    char*        fileData;      /* contents of the entire file */
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    long         fileLen;
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int          numThreads;
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ThreadEntry* threads;
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int          numMethods;
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry* methods;       /* 2 extra methods: "toplevel" and "unknown" */
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} DataKeys;
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define TOPLEVEL_INDEX 0
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define UNKNOWN_INDEX 1
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct StackEntry {
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry *method;
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t    entryTime;
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} StackEntry;
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct CallStack {
2017b522639a499f63ccb5162576830d0c20539bd05Andy McFadden    int         top;
2027b522639a499f63ccb5162576830d0c20539bd05Andy McFadden    StackEntry  calls[MAX_STACK_DEPTH];
2037b522639a499f63ccb5162576830d0c20539bd05Andy McFadden    uint64_t    lastEventTime;
2047b522639a499f63ccb5162576830d0c20539bd05Andy McFadden    uint64_t    threadStartTime;
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} CallStack;
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct DiffEntry {
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry* method1;
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry* method2;
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int64_t differenceExclusive;
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int64_t differenceInclusive;
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    double differenceExclusivePercentage;
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    double differenceInclusivePercentage;
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} DiffEntry;
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// Global options
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct Options {
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* traceFileName;
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* diffFileName;
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* graphFileName;
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int keepDotFile;
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int dump;
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int outputHtml;
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* sortableUrl;
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int threshold;
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} Options;
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct TraceData {
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numClasses;
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassEntry *classes;
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStack *stacks[MAX_THREADS];
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int depth[MAX_THREADS];
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numUniqueMethods;
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UniqueMethodEntry *uniqueMethods;
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} TraceData;
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic Options gOptions;
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Escapes characters in the source string that are html special entities.
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The escaped string is written to "dest" which must be large enough to
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * hold the result.  A pointer to "dest" is returned.  The characters and
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * their corresponding escape sequences are:
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  '<'  &lt;
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  '>'  &gt;
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  '&'  &amp;
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchar *htmlEscape(const char *src, char *dest, int len)
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char *destStart = dest;
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (src == NULL)
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int nbytes = 0;
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (*src) {
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*src == '<') {
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            nbytes += 4;
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (nbytes >= len)
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = '&';
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = 'l';
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = 't';
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = ';';
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (*src == '>') {
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            nbytes += 4;
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (nbytes >= len)
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = '&';
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = 'g';
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = 't';
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = ';';
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (*src == '&') {
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            nbytes += 5;
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (nbytes >= len)
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = '&';
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = 'a';
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = 'm';
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = 'p';
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = ';';
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            nbytes += 1;
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (nbytes >= len)
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *dest++ = *src;
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        src += 1;
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (nbytes >= len) {
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr, "htmlEscape(): buffer overflow\n");
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        exit(1);
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *dest = 0;
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return destStart;
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Initializes a MethodEntry
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid initMethodEntry(MethodEntry *method, unsigned int methodId,
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     const char *className, const char *methodName,
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     const char *signature, const char* fileName,
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     const char* lineNumStr)
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->methodId = methodId;
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->className = className;
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->methodName = methodName;
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->signature = signature;
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->fileName = fileName;
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->lineNum = (lineNumStr != NULL) ? atoi(lineNumStr) : -1;
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->elapsedExclusive = 0;
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->elapsedInclusive = 0;
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->topExclusive = 0;
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->recursiveInclusive = 0;
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->parents[0] = NULL;
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->parents[1] = NULL;
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->children[0] = NULL;
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->children[1] = NULL;
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->numCalls[0] = 0;
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->numCalls[1] = 0;
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->index = 0;
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->recursiveEntries = 0;
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This comparison function is called from qsort() to sort
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * methods into decreasing order of exclusive elapsed time.
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint compareElapsedExclusive(const void *a, const void *b) {
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t elapsed1, elapsed2;
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const MethodEntry *methodA = *(const MethodEntry**)a;
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const MethodEntry *methodB = *(const MethodEntry**)b;
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elapsed1 = methodA->elapsedExclusive;
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elapsed2 = methodB->elapsedExclusive;
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elapsed1 < elapsed2)
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elapsed1 > elapsed2)
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the elapsed times of two methods are equal, then sort them
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * into alphabetical order.
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = strcmp(methodA->className, methodB->className);
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result == 0) {
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodA->methodName == NULL || methodB->methodName == NULL) {
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            unsigned int idA = methodA->methodId;
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            unsigned int idB = methodB->methodId;
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (idA < idB)
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return -1;
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (idA > idB)
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return 1;
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 0;
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = strcmp(methodA->methodName, methodB->methodName);
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result == 0)
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result = strcmp(methodA->signature, methodB->signature);
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This comparison function is called from qsort() to sort
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * methods into decreasing order of inclusive elapsed time.
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint compareElapsedInclusive(const void *a, const void *b) {
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const MethodEntry *methodA, *methodB;
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t elapsed1, elapsed2;
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    methodA = *(MethodEntry const **)a;
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    methodB = *(MethodEntry const **)b;
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elapsed1 = methodA->elapsedInclusive;
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elapsed2 = methodB->elapsedInclusive;
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elapsed1 < elapsed2)
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elapsed1 > elapsed2)
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the elapsed times of two methods are equal, then sort them
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * into alphabetical order.
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = strcmp(methodA->className, methodB->className);
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result == 0) {
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodA->methodName == NULL || methodB->methodName == NULL) {
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            unsigned int idA = methodA->methodId;
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            unsigned int idB = methodB->methodId;
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (idA < idB)
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return -1;
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (idA > idB)
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return 1;
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 0;
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = strcmp(methodA->methodName, methodB->methodName);
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result == 0)
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result = strcmp(methodA->signature, methodB->signature);
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This comparison function is called from qsort() to sort
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TimedMethods into decreasing order of inclusive elapsed time.
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint compareTimedMethod(const void *a, const void *b) {
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const TimedMethod *timedA, *timedB;
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t elapsed1, elapsed2;
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    timedA = (TimedMethod const *)a;
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    timedB = (TimedMethod const *)b;
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elapsed1 = timedA->elapsedInclusive;
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elapsed2 = timedB->elapsedInclusive;
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elapsed1 < elapsed2)
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elapsed1 > elapsed2)
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the elapsed times of two methods are equal, then sort them
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * into alphabetical order.
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry *methodA = timedA->method;
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry *methodB = timedB->method;
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = strcmp(methodA->className, methodB->className);
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result == 0) {
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodA->methodName == NULL || methodB->methodName == NULL) {
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            unsigned int idA = methodA->methodId;
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            unsigned int idB = methodB->methodId;
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (idA < idB)
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return -1;
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (idA > idB)
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return 1;
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 0;
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = strcmp(methodA->methodName, methodB->methodName);
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result == 0)
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result = strcmp(methodA->signature, methodB->signature);
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This comparison function is called from qsort() to sort
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * MethodEntry pointers into alphabetical order of class names.
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint compareClassNames(const void *a, const void *b) {
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const MethodEntry *methodA = *(const MethodEntry**)a;
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const MethodEntry *methodB = *(const MethodEntry**)b;
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = strcmp(methodA->className, methodB->className);
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result == 0) {
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int idA = methodA->methodId;
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int idB = methodB->methodId;
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (idA < idB)
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (idA > idB)
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 1;
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 0;
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This comparison function is called from qsort() to sort
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * classes into decreasing order of exclusive elapsed time.
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint compareClassExclusive(const void *a, const void *b) {
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t elapsed1, elapsed2;
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassEntry *classA = *(const ClassEntry**)a;
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassEntry *classB = *(const ClassEntry**)b;
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elapsed1 = classA->elapsedExclusive;
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elapsed2 = classB->elapsedExclusive;
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elapsed1 < elapsed2)
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elapsed1 > elapsed2)
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the elapsed times of two classs are equal, then sort them
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * into alphabetical order.
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = strcmp(classA->className, classB->className);
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result == 0) {
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Break ties with the first method id.  This is probably not
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * needed.
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int idA = classA->methods[0]->methodId;
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int idB = classB->methods[0]->methodId;
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (idA < idB)
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (idA > idB)
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 1;
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 0;
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This comparison function is called from qsort() to sort
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * MethodEntry pointers into alphabetical order by method name,
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * then by class name.
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint compareMethodNames(const void *a, const void *b) {
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const MethodEntry *methodA = *(const MethodEntry**)a;
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const MethodEntry *methodB = *(const MethodEntry**)b;
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (methodA->methodName == NULL || methodB->methodName == NULL) {
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return compareClassNames(a, b);
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = strcmp(methodA->methodName, methodB->methodName);
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result == 0) {
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = strcmp(methodA->className, methodB->className);
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result == 0) {
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            unsigned int idA = methodA->methodId;
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            unsigned int idB = methodB->methodId;
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (idA < idB)
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return -1;
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (idA > idB)
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return 1;
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 0;
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This comparison function is called from qsort() to sort
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * unique methods into decreasing order of exclusive elapsed time.
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint compareUniqueExclusive(const void *a, const void *b) {
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t elapsed1, elapsed2;
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const UniqueMethodEntry *uniqueA = *(const UniqueMethodEntry**)a;
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const UniqueMethodEntry *uniqueB = *(const UniqueMethodEntry**)b;
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elapsed1 = uniqueA->elapsedExclusive;
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elapsed2 = uniqueB->elapsedExclusive;
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elapsed1 < elapsed2)
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elapsed1 > elapsed2)
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the elapsed times of two methods are equal, then sort them
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * into alphabetical order.
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = strcmp(uniqueA->methods[0]->className,
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    uniqueB->methods[0]->className);
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result == 0) {
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int idA = uniqueA->methods[0]->methodId;
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int idB = uniqueB->methods[0]->methodId;
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (idA < idB)
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (idA > idB)
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 1;
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 0;
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free a DataKeys struct.
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid freeDataKeys(DataKeys* pKeys)
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pKeys == NULL)
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(pKeys->fileData);
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(pKeys->threads);
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(pKeys->methods);
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(pKeys);
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the offset to the next occurrence of the specified character.
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "data" should point somewhere within the current line.  "len" is the
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * number of bytes left in the buffer.
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns -1 if we hit the end of the buffer.
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint findNextChar(const char* data, int len, char lookFor)
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* start = data;
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (len > 0) {
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*data == lookFor)
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return data - start;
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        data++;
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        len--;
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return -1;
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6017b522639a499f63ccb5162576830d0c20539bd05Andy McFadden/*
6027b522639a499f63ccb5162576830d0c20539bd05Andy McFadden * Count the number of lines until the next token.
6037b522639a499f63ccb5162576830d0c20539bd05Andy McFadden *
6047b522639a499f63ccb5162576830d0c20539bd05Andy McFadden * Returns -1 if none found before EOF.
6057b522639a499f63ccb5162576830d0c20539bd05Andy McFadden */
6067b522639a499f63ccb5162576830d0c20539bd05Andy McFaddenint countLinesToToken(const char* data, int len)
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int count = 0;
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int next;
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6117b522639a499f63ccb5162576830d0c20539bd05Andy McFadden    while (*data != TOKEN_CHAR) {
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        next = findNextChar(data, len, '\n');
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (next < 0)
6147b522639a499f63ccb5162576830d0c20539bd05Andy McFadden            return -1;
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        count++;
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        data += next+1;
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        len -= next+1;
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return count;
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Make sure we're at the start of the right section.
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the length of the token line, or -1 if something is wrong.
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint checkToken(const char* data, int len, const char* cmpStr)
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int cmpLen = strlen(cmpStr);
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int next;
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*data != TOKEN_CHAR) {
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr,
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "ERROR: not at start of %s (found '%.10s')\n", cmpStr, data);
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    next = findNextChar(data, len, '\n');
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (next < cmpLen+1)
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (strncmp(data+1, cmpStr, cmpLen) != 0) {
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr, "ERROR: '%s' not found (got '%.7s')\n", cmpStr, data+1);
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return next+1;
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parse the "*version" section.
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectlong parseVersion(DataKeys* pKeys, long offset, int verbose)
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* data;
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* dataEnd;
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, count, next;
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (offset < 0)
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data = pKeys->fileData + offset;
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dataEnd = pKeys->fileData + pKeys->fileLen;
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    next = checkToken(data, dataEnd - data, "version");
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (next <= 0)
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data += next;
670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Count the number of items in the "version" section.
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    count = countLinesToToken(data, dataEnd - data);
675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (count <= 0) {
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr,
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "ERROR: failed while reading version (found %d)\n", count);
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* find the end of the line */
682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    next = findNextChar(data, dataEnd - data, '\n');
683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (next < 0)
684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data[next] = '\0';
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    versionNumber = strtoul(data, NULL, 0);
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (verbose)
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("VERSION: %d\n", versionNumber);
690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data += next+1;
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* skip over the rest of the stuff, which is "name=value" lines */
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 1; i < count; i++) {
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        next = findNextChar(data, dataEnd - data, '\n');
696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (next < 0)
697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //data[next] = '\0';
699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //printf("IGNORING: '%s'\n", data);
700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        data += next+1;
701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return data - pKeys->fileData;
704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parse the "*threads" section.
708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectlong parseThreads(DataKeys* pKeys, long offset)
710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* data;
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* dataEnd;
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, next, tab, count;
714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (offset < 0)
716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data = pKeys->fileData + offset;
719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dataEnd = pKeys->fileData + pKeys->fileLen;
720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    next = checkToken(data, dataEnd - data, "threads");
721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data += next;
723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Count the number of thread entries (one per line).
726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    count = countLinesToToken(data, dataEnd - data);
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (count <= 0) {
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr,
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "ERROR: failed while reading threads (found %d)\n", count);
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //printf("+++ found %d threads\n", count);
735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pKeys->threads = (ThreadEntry*) malloc(sizeof(ThreadEntry) * count);
736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pKeys->threads == NULL)
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Extract all entries.
741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < count; i++) {
743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        next = findNextChar(data, dataEnd - data, '\n');
744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(next > 0);
745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        data[next] = '\0';
746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tab = findNextChar(data, next, '\t');
748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        data[tab] = '\0';
749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pKeys->threads[i].threadId = atoi(data);
751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pKeys->threads[i].threadName = data + tab +1;
752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        data += next+1;
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pKeys->numThreads = count;
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return data - pKeys->fileData;
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parse the "*methods" section.
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectlong parseMethods(DataKeys* pKeys, long offset)
764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* data;
766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* dataEnd;
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, next, count;
768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (offset < 0)
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data = pKeys->fileData + offset;
773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dataEnd = pKeys->fileData + pKeys->fileLen;
774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    next = checkToken(data, dataEnd - data, "methods");
775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (next < 0)
776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data += next;
779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Count the number of method entries (one per line).
782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    count = countLinesToToken(data, dataEnd - data);
784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (count <= 0) {
785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr,
786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "ERROR: failed while reading methods (found %d)\n", count);
787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Reserve an extra method at location 0 for the "toplevel" method,
791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and another extra method for all other "unknown" methods.
792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    count += 2;
794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pKeys->methods = (MethodEntry*) malloc(sizeof(MethodEntry) * count);
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pKeys->methods == NULL)
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    initMethodEntry(&pKeys->methods[TOPLEVEL_INDEX], 0, "(toplevel)",
798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        NULL, NULL, NULL, NULL);
799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    initMethodEntry(&pKeys->methods[UNKNOWN_INDEX], 0, "(unknown)",
800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        NULL, NULL, NULL, NULL);
801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Extract all entries, starting with index 2.
804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = UNKNOWN_INDEX + 1; i < count; i++) {
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int tab1, tab2, tab3, tab4, tab5;
807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int id;
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* endptr;
809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        next = findNextChar(data, dataEnd - data, '\n');
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(next > 0);
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        data[next] = '\0';
813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tab1 = findNextChar(data, next, '\t');
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tab2 = findNextChar(data+(tab1+1), next-(tab1+1), '\t');
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tab3 = findNextChar(data+(tab1+tab2+2), next-(tab1+tab2+2), '\t');
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tab4 = findNextChar(data+(tab1+tab2+tab3+3),
818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            next-(tab1+tab2+tab3+3), '\t');
819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tab5 = findNextChar(data+(tab1+tab2+tab3+tab4+4),
820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            next-(tab1+tab2+tab3+tab4+4), '\t');
821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (tab1 < 0) {
822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fprintf(stderr, "ERROR: missing field on method line: '%s'\n",
823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    data);
824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(data[tab1] == '\t');
827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        data[tab1] = '\0';
828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        id = strtoul(data, &endptr, 0);
830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*endptr != '\0') {
831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fprintf(stderr, "ERROR: bad method ID '%s'\n", data);
832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Allow files that specify just a function name, instead of requiring
836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // "class \t method \t signature"
837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (tab2 > 0 && tab3 > 0) {
838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tab2 += tab1+1;
839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tab3 += tab2+1;
840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(data[tab2] == '\t');
841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(data[tab3] == '\t');
842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            data[tab2] = data[tab3] = '\0';
843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // This is starting to get awkward.  Allow filename and line #.
845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (tab4 > 0 && tab5 > 0) {
846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                tab4 += tab3+1;
847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                tab5 += tab4+1;
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(data[tab4] == '\t');
850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(data[tab5] == '\t');
851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                data[tab4] = data[tab5] = '\0';
852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                initMethodEntry(&pKeys->methods[i], id, data + tab1 +1,
854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        data + tab2 +1, data + tab3 +1, data + tab4 +1,
855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        data + tab5 +1);
856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                initMethodEntry(&pKeys->methods[i], id, data + tab1 +1,
858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        data + tab2 +1, data + tab3 +1, NULL, NULL);
859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            initMethodEntry(&pKeys->methods[i], id, data + tab1 +1,
862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                NULL, NULL, NULL, NULL);
863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        data += next+1;
866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pKeys->numMethods = count;
869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return data - pKeys->fileData;
870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parse the "*end" section.
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectlong parseEnd(DataKeys* pKeys, long offset)
876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* data;
878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* dataEnd;
879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int next;
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (offset < 0)
882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data = pKeys->fileData + offset;
885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dataEnd = pKeys->fileData + pKeys->fileLen;
886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    next = checkToken(data, dataEnd - data, "end");
887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (next < 0)
888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data += next;
891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return data - pKeys->fileData;
893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sort the thread list entries.
897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int compareThreads(const void* thread1, const void* thread2)
899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return ((const ThreadEntry*) thread1)->threadId -
901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ((const ThreadEntry*) thread2)->threadId;
902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid sortThreadList(DataKeys* pKeys)
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(pKeys->threads, pKeys->numThreads, sizeof(pKeys->threads[0]),
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        compareThreads);
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sort the method list entries.
912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int compareMethods(const void* meth1, const void* meth2)
914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned int id1, id2;
916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    id1 = ((const MethodEntry*) meth1)->methodId;
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    id2 = ((const MethodEntry*) meth2)->methodId;
919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (id1 < id2)
920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (id1 > id2)
922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid sortMethodList(DataKeys* pKeys)
927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(pKeys->methods, pKeys->numMethods, sizeof(MethodEntry),
929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        compareMethods);
930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parse the key section, and return a copy of the parsed contents.
934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectDataKeys* parseKeys(FILE *fp, int verbose)
936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DataKeys* pKeys = NULL;
938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    long offset;
939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pKeys = (DataKeys*) calloc(1, sizeof(DataKeys));
942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pKeys == NULL)
943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto fail;
944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We load the entire file into memory.  We do this, rather than memory-
947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * mapping it, because we want to change some whitespace to NULs.
948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (fseek(fp, 0L, SEEK_END) != 0) {
950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        perror("fseek");
951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto fail;
952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pKeys->fileLen = ftell(fp);
954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pKeys->fileLen == 0) {
955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr, "Key file is empty.\n");
956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto fail;
957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    rewind(fp);
959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pKeys->fileData = (char*) malloc(pKeys->fileLen);
961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pKeys->fileData == NULL) {
962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr, "ERROR: unable to alloc %ld bytes\n", pKeys->fileLen);
963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto fail;
964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (fread(pKeys->fileData, 1, pKeys->fileLen, fp) != (size_t) pKeys->fileLen)
967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr, "ERROR: unable to read %ld bytes from trace file\n",
969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pKeys->fileLen);
970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto fail;
971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    offset = 0;
974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    offset = parseVersion(pKeys, offset, verbose);
976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    offset = parseThreads(pKeys, offset);
977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    offset = parseMethods(pKeys, offset);
978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    offset = parseEnd(pKeys, offset);
979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (offset < 0)
980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto fail;
981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
9827b522639a499f63ccb5162576830d0c20539bd05Andy McFadden    /* Reduce our allocation now that we know where the end of the key section is. */
9837b522639a499f63ccb5162576830d0c20539bd05Andy McFadden    pKeys->fileData = (char *)realloc(pKeys->fileData, offset);
9847b522639a499f63ccb5162576830d0c20539bd05Andy McFadden    pKeys->fileLen = offset;
985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Leave fp pointing to the beginning of the data section. */
986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fseek(fp, offset, SEEK_SET);
987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sortThreadList(pKeys);
989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sortMethodList(pKeys);
990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Dump list of threads.
993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (verbose) {
995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("Threads (%d):\n", pKeys->numThreads);
996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < pKeys->numThreads; i++) {
997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("%2d %s\n",
998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   pKeys->threads[i].threadId, pKeys->threads[i].threadName);
999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Dump list of methods.
1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (verbose) {
1007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("Methods (%d):\n", pKeys->numMethods);
1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < pKeys->numMethods; i++) {
1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("0x%08x %s : %s : %s\n",
10107b522639a499f63ccb5162576830d0c20539bd05Andy McFadden                   pKeys->methods[i].methodId, pKeys->methods[i].className,
1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   pKeys->methods[i].methodName, pKeys->methods[i].signature);
1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return pKeys;
1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfail:
1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    freeDataKeys(pKeys);
1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return NULL;
1021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Read values from the binary data file.
1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Make the return value "unsigned int" instead of "unsigned short" so that
1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we can detect EOF.
1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectunsigned int read2LE(FILE* fp)
1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned int val;
1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val = getc(fp);
1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= getc(fp) << 8;
1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return val;
1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectunsigned int read4LE(FILE* fp)
1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned int val;
1042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val = getc(fp);
1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= getc(fp) << 8;
1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= getc(fp) << 16;
1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= getc(fp) << 24;
1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return val;
1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectunsigned long long read8LE(FILE* fp)
1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned long long val;
1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val = getc(fp);
1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= (unsigned long long) getc(fp) << 8;
1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= (unsigned long long) getc(fp) << 16;
1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= (unsigned long long) getc(fp) << 24;
1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= (unsigned long long) getc(fp) << 32;
1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= (unsigned long long) getc(fp) << 40;
1059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= (unsigned long long) getc(fp) << 48;
1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val |= (unsigned long long) getc(fp) << 56;
1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return val;
1062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parse the header of the data section.
1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns with the file positioned at the start of the record data.
1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint parseDataHeader(FILE *fp, DataHeader* pHeader)
1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1071949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown    int bytesToRead;
1072949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown
1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pHeader->magic = read4LE(fp);
1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pHeader->version = read2LE(fp);
1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pHeader->offsetToData = read2LE(fp);
1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pHeader->startWhen = read8LE(fp);
1077949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown    bytesToRead = pHeader->offsetToData - 16;
1078949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown    if (pHeader->version == 1) {
1079949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown        pHeader->recordSize = 9;
1080949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown    } else if (pHeader->version == 2) {
1081949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown        pHeader->recordSize = 10;
1082949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown    } else if (pHeader->version == 3) {
1083949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown        pHeader->recordSize = read2LE(fp);
1084949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown        bytesToRead -= 2;
1085949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown    } else {
1086949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown        fprintf(stderr, "Unsupported trace file version: %d\n", pHeader->version);
1087949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown        return -1;
1088949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown    }
1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1090949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown    if (fseek(fp, bytesToRead, SEEK_CUR) != 0) {
1091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
1095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
10987b522639a499f63ccb5162576830d0c20539bd05Andy McFadden * Look up a method by it's method ID.
1099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns NULL if no matching method was found.
1101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectMethodEntry* lookupMethod(DataKeys* pKeys, unsigned int methodId)
1103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int hi, lo, mid;
1105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned int id;
1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    lo = 0;
1108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    hi = pKeys->numMethods - 1;
1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (hi >= lo) {
1111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mid = (hi + lo) / 2;
1112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        id = pKeys->methods[mid].methodId;
11147b522639a499f63ccb5162576830d0c20539bd05Andy McFadden        if (id == methodId)           /* match */
11157b522639a499f63ccb5162576830d0c20539bd05Andy McFadden            return &pKeys->methods[mid];
11167b522639a499f63ccb5162576830d0c20539bd05Andy McFadden        else if (id < methodId)       /* too low */
1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lo = mid + 1;
1118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else                          /* too high */
1119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hi = mid - 1;
1120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return NULL;
1123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Reads the next data record, and assigns the data values to threadId,
1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * methodVal and elapsedTime.  On end-of-file, the threadId, methodVal,
1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and elapsedTime are unchanged.  Returns 1 on end-of-file, otherwise
1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * returns 0.
1130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1131949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brownint readDataRecord(FILE *dataFp, DataHeader* dataHeader,
1132949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown        int *threadId, unsigned int *methodVal, uint64_t *elapsedTime)
1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int id;
1135949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown    int bytesToRead;
1136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1137949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown    bytesToRead = dataHeader->recordSize;
1138949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown    if (dataHeader->version == 1) {
1139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        id = getc(dataFp);
1140949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown        bytesToRead -= 1;
1141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        id = read2LE(dataFp);
1143949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown        bytesToRead -= 2;
1144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (id == EOF)
1146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
1147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *threadId = id;
1148de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *methodVal = read4LE(dataFp);
1150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *elapsedTime = read4LE(dataFp);
1151949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown    bytesToRead -= 8;
1152949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown
1153949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown    while (bytesToRead-- > 0) {
1154949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown        getc(dataFp);
1155949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown    }
1156949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown
1157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (feof(dataFp)) {
1158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr, "WARNING: hit EOF mid-record\n");
1159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
1160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
1162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Read the key file and use it to produce formatted output from the
1166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * data file.
1167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dumpTrace()
1169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static const char* actionStr[] = { "ent", "xit", "unr", "???" };
1171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry bogusMethod = { 0, "???", "???", "???", "???", -1, 0, 0, 0, 0,
1172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                {NULL, NULL}, {NULL, NULL}, {0, 0}, 0, 0, -1 };
1173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char bogusBuf[80];
1174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char spaces[MAX_STACK_DEPTH+1];
1175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    FILE* dataFp = NULL;
1176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DataHeader dataHeader;
1177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DataKeys* pKeys = NULL;
1178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    TraceData traceData;
1180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //printf("Dumping '%s' '%s'\n", dataFileName, keyFileName);
1182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(spaces, '.', MAX_STACK_DEPTH);
1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    spaces[MAX_STACK_DEPTH] = '\0';
1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < MAX_THREADS; i++)
1187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        traceData.depth[i] = 2;       // adjust for return from start function
1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dataFp = fopen(gOptions.traceFileName, "r");
1190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dataFp == NULL)
1191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((pKeys = parseKeys(dataFp, 1)) == NULL)
1194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (parseDataHeader(dataFp, &dataHeader) < 0)
1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("Trace (threadID action usecs class.method signature):\n");
1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (1) {
1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        MethodEntry* method;
1203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int threadId;
1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int methodVal;
1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        uint64_t elapsedTime;
1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int action, printDepth;
1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int methodId, lastEnter = 0;
1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int mismatch = 0;
1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char depthNote;
1210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Extract values from file.
1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1214949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown        if (readDataRecord(dataFp, &dataHeader, &threadId, &methodVal, &elapsedTime))
1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        action = METHOD_ACTION(methodVal);
1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodId = METHOD_ID(methodVal);
1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Generate a line of output.
1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (action == METHOD_TRACE_ENTER) {
1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            traceData.depth[threadId]++;
1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lastEnter = methodId;
1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* quick test for mismatched adjacent enter/exit */
1228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (lastEnter != 0 && lastEnter != methodId)
1229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                mismatch = 1;
1230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printDepth = traceData.depth[threadId];
1233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        depthNote = ' ';
1234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (printDepth < 0) {
1235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printDepth = 0;
1236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            depthNote = '-';
1237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (printDepth > MAX_STACK_DEPTH) {
1238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printDepth = MAX_STACK_DEPTH;
1239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            depthNote = '+';
1240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        method = lookupMethod(pKeys, methodId);
1243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method == NULL) {
1244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method = &bogusMethod;
1245291c84f60853d30e1c0d79dd08c5e5164f588e26Dan Bornstein            sprintf(bogusBuf, "methodId: %#x", methodId);
1246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->signature = bogusBuf;
1247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project	if (method->methodName) {
1250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project	    printf("%2d %s%c %8lld%c%s%s.%s %s\n", threadId,
1251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project		   actionStr[action], mismatch ? '!' : ' ',
1252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project		   elapsedTime, depthNote,
1253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project		   spaces + (MAX_STACK_DEPTH - printDepth),
1254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project		   method->className, method->methodName, method->signature);
1255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project	} else {
1256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project	    printf("%2d %s%c %8lld%c%s%s\n", threadId,
1257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project		   actionStr[action], mismatch ? '!' : ' ',
1258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project		   elapsedTime, depthNote,
1259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project		   spaces + (MAX_STACK_DEPTH - printDepth),
1260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project		   method->className);
1261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project	}
1262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (action != METHOD_TRACE_ENTER) {
1264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            traceData.depth[threadId]--;  /* METHOD_TRACE_EXIT or METHOD_TRACE_UNROLL */
1265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lastEnter = 0;
1266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mismatch = 0;
1269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
1272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dataFp != NULL)
1273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fclose(dataFp);
1274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pKeys != NULL)
1275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        freeDataKeys(pKeys);
1276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* This routine adds the given time to the parent and child methods.
1279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is called when the child routine exits, after the child has
1280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * been popped from the stack.  The elapsedTime parameter is the
1281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * duration of the child routine, including time spent in called routines.
1282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid addInclusiveTime(MethodEntry *parent, MethodEntry *child,
1284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                      uint64_t elapsedTime)
1285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    TimedMethod *pTimed;
1287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
1289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool verbose = false;
1290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (strcmp(child->className, debugClassName) == 0)
1291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        verbose = true;
1292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int childIsRecursive = (child->recursiveEntries > 0);
1295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int parentIsRecursive = (parent->recursiveEntries > 1);
1296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (child->recursiveEntries == 0) {
1298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        child->elapsedInclusive += elapsedTime;
1299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else if (child->recursiveEntries == 1) {
1300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        child->recursiveInclusive += elapsedTime;
1301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    child->numCalls[childIsRecursive] += 1;
1303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
1305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (verbose) {
1306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr,
1307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "%s %d elapsedTime: %lld eI: %lld, rI: %lld\n",
1308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                child->className, child->recursiveEntries,
1309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                elapsedTime, child->elapsedInclusive,
1310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                child->recursiveInclusive);
1311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Find the child method in the parent */
1315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    TimedMethod *children = parent->children[parentIsRecursive];
1316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (pTimed = children; pTimed; pTimed = pTimed->next) {
1317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pTimed->method == child) {
1318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pTimed->elapsedInclusive += elapsedTime;
1319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pTimed->numCalls += 1;
1320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pTimed == NULL) {
1324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Allocate a new TimedMethod */
1325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pTimed = (TimedMethod *) malloc(sizeof(TimedMethod));
1326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pTimed->elapsedInclusive = elapsedTime;
1327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pTimed->numCalls = 1;
1328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pTimed->method = child;
1329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Add it to the front of the list */
1331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pTimed->next = children;
1332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        parent->children[parentIsRecursive] = pTimed;
1333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Find the parent method in the child */
1336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    TimedMethod *parents = child->parents[childIsRecursive];
1337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (pTimed = parents; pTimed; pTimed = pTimed->next) {
1338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pTimed->method == parent) {
1339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pTimed->elapsedInclusive += elapsedTime;
1340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pTimed->numCalls += 1;
1341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pTimed == NULL) {
1345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Allocate a new TimedMethod */
1346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pTimed = (TimedMethod *) malloc(sizeof(TimedMethod));
1347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pTimed->elapsedInclusive = elapsedTime;
1348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pTimed->numCalls = 1;
1349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pTimed->method = parent;
1350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Add it to the front of the list */
1352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pTimed->next = parents;
1353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        child->parents[childIsRecursive] = pTimed;
1354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
1357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (verbose) {
1358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr,
1359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "  %s %d eI: %lld\n",
1360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                parent->className, parent->recursiveEntries,
1361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pTimed->elapsedInclusive);
1362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Sorts a linked list and returns a newly allocated array containing
1367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the sorted entries.
1368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectTimedMethod *sortTimedMethodList(TimedMethod *list, int *num)
1370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii;
1372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    TimedMethod *pTimed, *sorted;
1373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Count the elements */
1375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int num_entries = 0;
1376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (pTimed = list; pTimed; pTimed = pTimed->next)
1377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        num_entries += 1;
1378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *num = num_entries;
1379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (num_entries == 0)
1380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
1381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Copy all the list elements to a new array and sort them */
1383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sorted = (TimedMethod *) malloc(sizeof(TimedMethod) * num_entries);
1384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0, pTimed = list; pTimed; pTimed = pTimed->next, ++ii)
1385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        memcpy(&sorted[ii], pTimed, sizeof(TimedMethod));
1386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(sorted, num_entries, sizeof(TimedMethod), compareTimedMethod);
1387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Fix up the "next" pointers so that they work. */
1389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < num_entries - 1; ++ii)
1390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sorted[ii].next = &sorted[ii + 1];
1391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sorted[num_entries - 1].next = NULL;
1392de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return sorted;
1394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Define flag values for printInclusiveMethod() */
1397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic const int kIsRecursive = 1;
1398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* This prints the inclusive stats for all the parents or children of a
1400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * method, depending on the list that is passed in.
1401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid printInclusiveMethod(MethodEntry *method, TimedMethod *list, int numCalls,
1403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                          int flags)
1404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int num;
1406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    TimedMethod *pTimed;
1407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char buf[80];
1408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char *anchor_close;
1409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char *spaces = "      ";    /* 6 spaces */
1410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int num_spaces = strlen(spaces);
1411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char *space_ptr = &spaces[num_spaces];
1412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char *className, *methodName, *signature;
1413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char classBuf[HTML_BUFSIZE], methodBuf[HTML_BUFSIZE];
1414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char signatureBuf[HTML_BUFSIZE];
1415de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    anchor_close = "";
1417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml)
1418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        anchor_close = "</a>";
1419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    TimedMethod *sorted = sortTimedMethodList(list,  &num);
1421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    double methodTotal = method->elapsedInclusive;
1422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (pTimed = sorted; pTimed; pTimed = pTimed->next) {
1423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        MethodEntry *relative = pTimed->method;
1424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        className = (char*)(relative->className);
1425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodName = (char*)(relative->methodName);
1426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        signature = (char*)(relative->signature);
1427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        double per = 100.0 * pTimed->elapsedInclusive / methodTotal;
1428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sprintf(buf, "[%d]", relative->index);
1429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) {
1430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int len = strlen(buf);
1431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (len > num_spaces)
1432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                len = num_spaces;
1433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "<a href=\"#m%d\">[%d]",
1434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    relative->index, relative->index);
1435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            space_ptr = &spaces[len];
1436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            className = htmlEscape(className, classBuf, HTML_BUFSIZE);
1437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodName = htmlEscape(methodName, methodBuf, HTML_BUFSIZE);
1438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            signature = htmlEscape(signature, signatureBuf, HTML_BUFSIZE);
1439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int nCalls = numCalls;
1441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (nCalls == 0)
1442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            nCalls = relative->numCalls[0] + relative->numCalls[1];
1443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (relative->methodName) {
1444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (flags & kIsRecursive) {
1445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // Don't display percentages for recursive functions
1446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("%6s %5s   %6s %s%6s%s %6d/%-6d %9llu %s.%s %s\n",
1447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       "", "", "",
1448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       space_ptr, buf, anchor_close,
1449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       pTimed->numCalls, nCalls,
1450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       pTimed->elapsedInclusive,
1451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       className, methodName, signature);
1452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
1453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("%6s %5s   %5.1f%% %s%6s%s %6d/%-6d %9llu %s.%s %s\n",
1454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       "", "", per,
1455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       space_ptr, buf, anchor_close,
1456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       pTimed->numCalls, nCalls,
1457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       pTimed->elapsedInclusive,
1458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       className, methodName, signature);
1459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (flags & kIsRecursive) {
1462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // Don't display percentages for recursive functions
1463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("%6s %5s   %6s %s%6s%s %6d/%-6d %9llu %s\n",
1464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       "", "", "",
1465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       space_ptr, buf, anchor_close,
1466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       pTimed->numCalls, nCalls,
1467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       pTimed->elapsedInclusive,
1468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       className);
1469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
1470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("%6s %5s   %5.1f%% %s%6s%s %6d/%-6d %9llu %s\n",
1471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       "", "", per,
1472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       space_ptr, buf, anchor_close,
1473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       pTimed->numCalls, nCalls,
1474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       pTimed->elapsedInclusive,
1475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       className);
1476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid countRecursiveEntries(CallStack *pStack, int top, MethodEntry *method)
1482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii;
1484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->recursiveEntries = 0;
1486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < top; ++ii) {
1487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pStack->calls[ii].method == method)
1488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->recursiveEntries += 1;
1489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid stackDump(CallStack *pStack, int top)
1493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii;
1495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < top; ++ii) {
1497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        MethodEntry *method = pStack->calls[ii].method;
1498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        uint64_t entryTime = pStack->calls[ii].entryTime;
1499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method->methodName) {
1500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fprintf(stderr, "  %2d: %8llu %s.%s %s\n", ii, entryTime,
1501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   method->className, method->methodName, method->signature);
1502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fprintf(stderr, "  %2d: %8llu %s\n", ii, entryTime, method->className);
1504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid outputTableOfContents()
1509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("<a name=\"contents\"></a>\n");
1511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("<h2>Table of Contents</h2>\n");
1512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("<ul>\n");
1513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("  <li><a href=\"#exclusive\">Exclusive profile</a></li>\n");
1514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("  <li><a href=\"#inclusive\">Inclusive profile</a></li>\n");
1515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("  <li><a href=\"#class\">Class/method profile</a></li>\n");
1516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("  <li><a href=\"#method\">Method/class profile</a></li>\n");
1517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("</ul>\n\n");
1518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid outputNavigationBar()
1521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("<a href=\"#contents\">[Top]</a>\n");
1523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("<a href=\"#exclusive\">[Exclusive]</a>\n");
1524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("<a href=\"#inclusive\">[Inclusive]</a>\n");
1525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("<a href=\"#class\">[Class]</a>\n");
1526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("<a href=\"#method\">[Method]</a>\n");
1527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("<br><br>\n");
1528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid printExclusiveProfile(MethodEntry **pMethods, int numMethods,
1531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                           uint64_t sumThreadTime)
1532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii;
1534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry* method;
1535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    double total, sum, per, sum_per;
1536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char classBuf[HTML_BUFSIZE], methodBuf[HTML_BUFSIZE];
1537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char signatureBuf[HTML_BUFSIZE];
1538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char anchor_buf[80];
1539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char *anchor_close = "";
1540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    total = sumThreadTime;
1542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    anchor_buf[0] = 0;
1543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
1544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        anchor_close = "</a>";
1545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<a name=\"exclusive\"></a>\n");
1546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<hr>\n");
1547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        outputNavigationBar();
1548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("\n%s\n", profileSeparator);
1550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* First, sort the methods into decreasing order of inclusive
1553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * elapsed time so that we can assign the method indices.
1554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(pMethods, numMethods, sizeof(MethodEntry*), compareElapsedInclusive);
1556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numMethods; ++ii)
1558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pMethods[ii]->index = ii;
1559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Sort the methods into decreasing order of exclusive elapsed time.
1561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(pMethods, numMethods, sizeof(MethodEntry*),
1563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project          compareElapsedExclusive);
1564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("Total cycles: %llu\n\n", sumThreadTime);
1566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
1567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<br><br>\n");
1568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("Exclusive elapsed times for each method, not including time spent in\n");
1570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("children, sorted by exclusive time.\n\n");
1571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
1572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<br><br>\n<pre>\n");
1573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("    Usecs  self %%  sum %%  Method\n");
1576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sum = 0;
1577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numMethods; ++ii) {
1579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char *className, *methodName, *signature;
1580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        method = pMethods[ii];
1582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Don't show methods with zero cycles */
1583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method->elapsedExclusive == 0)
1584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        className = (char*)(method->className);
1586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodName = (char*)(method->methodName);
1587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        signature = (char*)(method->signature);
1588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sum += method->elapsedExclusive;
1589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        per = 100.0 * method->elapsedExclusive / total;
1590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sum_per = 100.0 * sum / total;
1591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) {
1592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(anchor_buf, "<a href=\"#m%d\">", method->index);
1593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            className = htmlEscape(className, classBuf, HTML_BUFSIZE);
1594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodName = htmlEscape(methodName, methodBuf, HTML_BUFSIZE);
1595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            signature = htmlEscape(signature, signatureBuf, HTML_BUFSIZE);
1596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method->methodName) {
1598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("%9llu  %6.2f %6.2f  %s[%d]%s %s.%s %s\n",
1599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   method->elapsedExclusive, per, sum_per,
1600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   anchor_buf, method->index, anchor_close,
1601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   className, methodName, signature);
1602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("%9llu  %6.2f %6.2f  %s[%d]%s %s\n",
1604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   method->elapsedExclusive, per, sum_per,
1605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   anchor_buf, method->index, anchor_close,
1606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   className);
1607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
1610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("</pre>\n");
1611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* check to make sure that the child method meets the threshold of the parent */
1615de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiroint checkThreshold(MethodEntry* parent, MethodEntry* child)
1616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    double parentTime = parent->elapsedInclusive;
1618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    double childTime = child->elapsedInclusive;
1619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int64_t percentage = (childTime / parentTime) * 100.0;
1620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (percentage < gOptions.threshold) ? 0 : 1;
1621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid createLabels(FILE* file, MethodEntry* method)
1624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1625de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro    fprintf(file, "node%d[label = \"[%d] %s.%s (%llu, %llu, %d)\"]\n",
1626de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro             method->index, method->index, method->className, method->methodName,
1627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             method->elapsedInclusive / 1000,
1628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             method->elapsedExclusive / 1000,
1629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             method->numCalls[0]);
1630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1631de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro    method->graphState = GRAPH_LABEL_VISITED;
1632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    TimedMethod* child;
1634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (child = method->children[0] ; child ; child = child->next) {
1635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        MethodEntry* childMethod = child->method;
1636de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((childMethod->graphState & GRAPH_LABEL_VISITED) == 0 && checkThreshold(method, childMethod)) {
1638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            createLabels(file, child->method);
1639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid createLinks(FILE* file, MethodEntry* method)
1644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->graphState |= GRAPH_NODE_VISITED;
1646de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    TimedMethod* child;
1648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (child = method->children[0] ; child ; child = child->next) {
1649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        MethodEntry* childMethod = child->method;
1650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (checkThreshold(method, child->method)) {
1651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fprintf(file, "node%d -> node%d\n", method->index, child->method->index);
1652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // only visit children that haven't been visited before
1653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ((childMethod->graphState & GRAPH_NODE_VISITED) == 0) {
1654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                createLinks(file, child->method);
1655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid createInclusiveProfileGraphNew(DataKeys* dataKeys)
1661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // create a temporary file in /tmp
1663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char path[FILENAME_MAX];
1664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.keepDotFile) {
1665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        snprintf(path, FILENAME_MAX, "%s.dot", gOptions.graphFileName);
1666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        snprintf(path, FILENAME_MAX, "/tmp/dot-%d-%d.dot", (int)time(NULL), rand());
1668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    FILE* file = fopen(path, "w+");
1671de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(file, "digraph g {\nnode [shape = record,height=.1];\n");
1673de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    createLabels(file, dataKeys->methods);
1675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    createLinks(file, dataKeys->methods);
1676de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(file, "}");
1678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fclose(file);
1679de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // now that we have the dot file generate the image
1681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char command[1024];
1682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    snprintf(command, 1024, "dot -Tpng -o '%s' '%s'", gOptions.graphFileName, path);
1683de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    system(command);
1685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (! gOptions.keepDotFile) {
1687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        remove(path);
1688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid printInclusiveProfile(MethodEntry **pMethods, int numMethods,
1692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                           uint64_t sumThreadTime)
1693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii;
1695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry* method;
1696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    double total, sum, per, sum_per;
1697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char classBuf[HTML_BUFSIZE], methodBuf[HTML_BUFSIZE];
1698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char signatureBuf[HTML_BUFSIZE];
1699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char anchor_buf[80];
17007b522639a499f63ccb5162576830d0c20539bd05Andy McFadden    char *anchor_close = "";
1701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    total = sumThreadTime;
1703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    anchor_buf[0] = 0;
1704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
17057b522639a499f63ccb5162576830d0c20539bd05Andy McFadden        anchor_close = "</a>";
1706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<a name=\"inclusive\"></a>\n");
1707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<hr>\n");
1708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        outputNavigationBar();
1709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("\n%s\n", profileSeparator);
1711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Sort the methods into decreasing order of inclusive elapsed time. */
1714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(pMethods, numMethods, sizeof(MethodEntry*),
1715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project          compareElapsedInclusive);
1716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("\nInclusive elapsed times for each method and its parents and children,\n");
1718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("sorted by inclusive time.\n\n");
1719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
1721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<br><br>\n<pre>\n");
1722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("index  %%/total %%/self  index     calls         usecs name\n");
1725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numMethods; ++ii) {
1726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int num;
1727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        TimedMethod *pTimed;
1728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        double excl_per;
1729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char buf[40];
1730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char *className, *methodName, *signature;
1731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        method = pMethods[ii];
1733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Don't show methods with zero cycles */
1734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method->elapsedInclusive == 0)
1735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        className = (char*)(method->className);
1738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodName = (char*)(method->methodName);
1739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        signature = (char*)(method->signature);
1740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) {
1742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("<a name=\"m%d\"></a>", method->index);
1743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            className = htmlEscape(className, classBuf, HTML_BUFSIZE);
1744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodName = htmlEscape(methodName, methodBuf, HTML_BUFSIZE);
1745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            signature = htmlEscape(signature, signatureBuf, HTML_BUFSIZE);
1746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("----------------------------------------------------\n");
1748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Sort and print the parents */
1750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int numCalls = method->numCalls[0] + method->numCalls[1];
1751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printInclusiveMethod(method, method->parents[0], numCalls, 0);
1752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method->parents[1]) {
1753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("               +++++++++++++++++++++++++\n");
1754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printInclusiveMethod(method, method->parents[1], numCalls,
1755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                 kIsRecursive);
1756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        per = 100.0 * method->elapsedInclusive / total;
1759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sprintf(buf, "[%d]", ii);
1760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method->methodName) {
1761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("%-6s %5.1f%%   %5s %6s %6d+%-6d %9llu %s.%s %s\n",
1762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   buf,
1763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   per, "", "", method->numCalls[0], method->numCalls[1],
1764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   method->elapsedInclusive,
1765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   className, methodName, signature);
1766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("%-6s %5.1f%%   %5s %6s %6d+%-6d %9llu %s\n",
1768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   buf,
1769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   per, "", "", method->numCalls[0], method->numCalls[1],
1770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   method->elapsedInclusive,
1771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   className);
1772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        excl_per = 100.0 * method->topExclusive / method->elapsedInclusive;
1774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%6s %5s   %5.1f%% %6s %6s %6s %9llu\n",
1775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               "", "", excl_per, "excl", "", "", method->topExclusive);
1776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Sort and print the children */
1778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printInclusiveMethod(method, method->children[0], 0, 0);
1779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method->children[1]) {
1780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("               +++++++++++++++++++++++++\n");
1781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printInclusiveMethod(method, method->children[1], 0,
1782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                 kIsRecursive);
1783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
1786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("</pre>\n");
1787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid createClassList(TraceData* traceData, MethodEntry **pMethods, int numMethods)
1791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii;
1793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Sort the methods into alphabetical order to find the unique class
1795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * names.
1796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(pMethods, numMethods, sizeof(MethodEntry*), compareClassNames);
1798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Count the number of unique class names. */
1800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char *currentClassName = "";
1801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char *firstClassName = NULL;
1802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    traceData->numClasses = 0;
1803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numMethods; ++ii) {
1804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pMethods[ii]->methodName == NULL) {
1805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
1806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(pMethods[ii]->className, currentClassName) != 0) {
1808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Remember the first one
1809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (firstClassName == NULL) {
1810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                firstClassName = pMethods[ii]->className;
1811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            traceData->numClasses += 1;
1813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            currentClassName = pMethods[ii]->className;
1814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (traceData->numClasses == 0) {
1818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        traceData->classes = NULL;
1819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Allocate space for all of the unique class names */
1823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    traceData->classes = (ClassEntry *) malloc(sizeof(ClassEntry) * traceData->numClasses);
1824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Initialize the classes array */
1826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(traceData->classes, 0, sizeof(ClassEntry) * traceData->numClasses);
1827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassEntry *pClass = traceData->classes;
1828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pClass->className = currentClassName = firstClassName;
1829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int prevNumMethods = 0;
1830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numMethods; ++ii) {
1831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pMethods[ii]->methodName == NULL) {
1832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
1833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(pMethods[ii]->className, currentClassName) != 0) {
1835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pClass->numMethods = prevNumMethods;
1836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (++pClass)->className = currentClassName = pMethods[ii]->className;
1837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            prevNumMethods = 0;
1838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        prevNumMethods += 1;
1840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pClass->numMethods = prevNumMethods;
1842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Create the array of MethodEntry pointers for each class */
1844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pClass = NULL;
1845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    currentClassName = "";
1846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int nextMethod = 0;
1847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numMethods; ++ii) {
1848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pMethods[ii]->methodName == NULL) {
1849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
1850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(pMethods[ii]->className, currentClassName) != 0) {
1852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            currentClassName = pMethods[ii]->className;
1853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (pClass == NULL)
1854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pClass = traceData->classes;
1855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            else
1856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pClass++;
1857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Allocate space for the methods array */
1858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int nbytes = sizeof(MethodEntry*) * pClass->numMethods;
1859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pClass->methods = (MethodEntry**) malloc(nbytes);
1860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            nextMethod = 0;
1861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pClass->methods[nextMethod++] = pMethods[ii];
1863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Prints a number of html non-breaking spaces according so that the length
1867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of the string "buf" is at least "width" characters wide.  If width is
1868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * negative, then trailing spaces are added instead of leading spaces.
1869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid printHtmlField(char *buf, int width)
1871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii;
1873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int leadingSpaces = 1;
1875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (width < 0) {
1876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        width = -width;
1877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        leadingSpaces = 0;
1878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int len = strlen(buf);
1880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numSpaces = width - len;
1881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (numSpaces <= 0) {
1882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%s", buf);
1883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (leadingSpaces == 0)
1886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%s", buf);
1887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numSpaces; ++ii)
1888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("&nbsp;");
1889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (leadingSpaces == 1)
1890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%s", buf);
1891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid printClassProfiles(TraceData* traceData, uint64_t sumThreadTime)
1894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii, jj;
1896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry* method;
1897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    double total, sum, per, sum_per;
1898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char classBuf[HTML_BUFSIZE], methodBuf[HTML_BUFSIZE];
1899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char signatureBuf[HTML_BUFSIZE];
1900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    total = sumThreadTime;
1902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
1903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<a name=\"class\"></a>\n");
1904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<hr>\n");
1905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        outputNavigationBar();
1906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("\n%s\n", profileSeparator);
1908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (traceData->numClasses == 0) {
1911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("\nNo classes.\n");
1912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) {
1913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("<br><br>\n");
1914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("\nExclusive elapsed time for each class, summed over all the methods\n");
1919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("in the class.\n\n");
1920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
1921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<br><br>\n");
1922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* For each class, sum the exclusive times in all of the methods
1925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in that class.  Also sum the number of method calls.  Also
1926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * sort the methods so the most expensive appear at the top.
1927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassEntry *pClass = traceData->classes;
1929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < traceData->numClasses; ++ii, ++pClass) {
1930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //printf("%s %d methods\n", pClass->className, pClass->numMethods);
1931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int numMethods = pClass->numMethods;
1932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (jj = 0; jj < numMethods; ++jj) {
1933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method = pClass->methods[jj];
1934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pClass->elapsedExclusive += method->elapsedExclusive;
1935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pClass->numCalls[0] += method->numCalls[0];
1936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pClass->numCalls[1] += method->numCalls[1];
1937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Sort the methods into decreasing order of exclusive time */
1940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        qsort(pClass->methods, numMethods, sizeof(MethodEntry*),
1941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project              compareElapsedExclusive);
1942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Allocate an array of pointers to the classes for more efficient
1945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * sorting.
1946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassEntry **pClasses;
1948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pClasses = (ClassEntry**) malloc(sizeof(ClassEntry*) * traceData->numClasses);
1949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < traceData->numClasses; ++ii)
1950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pClasses[ii] = &traceData->classes[ii];
1951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Sort the classes into decreasing order of exclusive time */
1953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(pClasses, traceData->numClasses, sizeof(ClassEntry*), compareClassExclusive);
1954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
1956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<div class=\"header\"><span class=\"parent\">&nbsp;</span>&nbsp;&nbsp;&nbsp;");
1957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("Cycles %%/total Cumul.%% &nbsp;Calls+Recur&nbsp; Class</div>\n");
1958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("   Cycles %%/total Cumul.%%  Calls+Recur  Class\n");
1960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sum = 0;
1963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < traceData->numClasses; ++ii) {
1964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char *className, *methodName, *signature;
1965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Skip classes with zero cycles */
1967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pClass = pClasses[ii];
1968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pClass->elapsedExclusive == 0)
1969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        per = 100.0 * pClass->elapsedExclusive / total;
1972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sum += pClass->elapsedExclusive;
1973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sum_per = 100.0 * sum / total;
1974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        className = (char*)(pClass->className);
1975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) {
1976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            char buf[80];
1977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            className = htmlEscape(className, classBuf, HTML_BUFSIZE);
1979f6c387128427e121477c1b32ad35cdcaa5101ba3The 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);
1980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "%llu", pClass->elapsedExclusive);
1981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printHtmlField(buf, 9);
1982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" ");
1983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "%.1f", per);
1984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printHtmlField(buf, 7);
1985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" ");
1986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "%.1f", sum_per);
1987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printHtmlField(buf, 7);
1988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" ");
1989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "%d", pClass->numCalls[0]);
1990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printHtmlField(buf, 6);
1991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("+");
1992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "%d", pClass->numCalls[1]);
1993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printHtmlField(buf, -6);
1994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" ");
1995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("%s", className);
1996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("</div>\n");
1997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("<div class=\"parent\" id=\"d%d\">\n", ii);
1998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("---------------------------------------------\n");
2000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("%9llu %7.1f %7.1f %6d+%-6d %s\n",
2001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   pClass->elapsedExclusive, per, sum_per,
2002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   pClass->numCalls[0], pClass->numCalls[1],
2003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   className);
2004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int numMethods = pClass->numMethods;
2007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        double classExclusive = pClass->elapsedExclusive;
2008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        double sumMethods = 0;
2009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (jj = 0; jj < numMethods; ++jj) {
2010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method = pClass->methods[jj];
2011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodName = (char*)(method->methodName);
2012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            signature = (char*)(method->signature);
2013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            per = 100.0 * method->elapsedExclusive / classExclusive;
2014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sumMethods += method->elapsedExclusive;
2015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sum_per = 100.0 * sumMethods / classExclusive;
2016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (gOptions.outputHtml) {
2017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                char buf[80];
2018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                methodName = htmlEscape(methodName, methodBuf, HTML_BUFSIZE);
2020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                signature = htmlEscape(signature, signatureBuf, HTML_BUFSIZE);
2021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("<div class=\"leaf\"><span class=\"leaf\">&nbsp;</span>");
2022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%llu", method->elapsedExclusive);
2023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, 9);
2024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("&nbsp;");
2025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%llu", method->elapsedInclusive);
2026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, 9);
2027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("&nbsp;");
2028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%.1f", per);
2029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, 7);
2030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("&nbsp;");
2031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%.1f", sum_per);
2032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, 7);
2033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("&nbsp;");
2034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%d", method->numCalls[0]);
2035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, 6);
2036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("+");
2037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%d", method->numCalls[1]);
2038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, -6);
2039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("&nbsp;");
2040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("<a href=\"#m%d\">[%d]</a>&nbsp;%s&nbsp;%s",
2041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       method->index, method->index, methodName, signature);
2042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("</div>\n");
2043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
2044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("%9llu %9llu %7.1f %7.1f %6d+%-6d [%d] %s %s\n",
2045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       method->elapsedExclusive,
2046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       method->elapsedInclusive,
2047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       per, sum_per,
2048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       method->numCalls[0], method->numCalls[1],
2049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       method->index, methodName, signature);
2050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) {
2053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("</div>\n");
2054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid createUniqueMethodList(TraceData* traceData, MethodEntry **pMethods, int numMethods)
2059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii;
2061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Sort the methods into alphabetical order of method names
2063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to find the unique method names.
2064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(pMethods, numMethods, sizeof(MethodEntry*), compareMethodNames);
2066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Count the number of unique method names, ignoring class and
2068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * signature.
2069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char *currentMethodName = "";
2071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    traceData->numUniqueMethods = 0;
2072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numMethods; ++ii) {
2073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pMethods[ii]->methodName == NULL)
2074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
2075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(pMethods[ii]->methodName, currentMethodName) != 0) {
2076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            traceData->numUniqueMethods += 1;
2077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            currentMethodName = pMethods[ii]->methodName;
2078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (traceData->numUniqueMethods == 0)
2081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
2082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Allocate space for pointers to all of the unique methods */
2084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int nbytes = sizeof(UniqueMethodEntry) * traceData->numUniqueMethods;
2085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    traceData->uniqueMethods = (UniqueMethodEntry *) malloc(nbytes);
2086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Initialize the uniqueMethods array */
2088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(traceData->uniqueMethods, 0, nbytes);
2089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UniqueMethodEntry *pUnique = traceData->uniqueMethods;
2090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    currentMethodName = NULL;
2091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int prevNumMethods = 0;
2092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numMethods; ++ii) {
2093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pMethods[ii]->methodName == NULL)
2094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
2095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (currentMethodName == NULL)
2096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            currentMethodName = pMethods[ii]->methodName;
2097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(pMethods[ii]->methodName, currentMethodName) != 0) {
2098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            currentMethodName = pMethods[ii]->methodName;
2099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pUnique->numMethods = prevNumMethods;
2100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pUnique++;
2101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            prevNumMethods = 0;
2102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        prevNumMethods += 1;
2104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pUnique->numMethods = prevNumMethods;
2106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Create the array of MethodEntry pointers for each unique method */
2108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pUnique = NULL;
2109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    currentMethodName = "";
2110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int nextMethod = 0;
2111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numMethods; ++ii) {
2112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pMethods[ii]->methodName == NULL)
2113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
2114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(pMethods[ii]->methodName, currentMethodName) != 0) {
2115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            currentMethodName = pMethods[ii]->methodName;
2116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (pUnique == NULL)
2117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pUnique = traceData->uniqueMethods;
2118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            else
2119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pUnique++;
2120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Allocate space for the methods array */
2121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int nbytes = sizeof(MethodEntry*) * pUnique->numMethods;
2122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pUnique->methods = (MethodEntry**) malloc(nbytes);
2123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            nextMethod = 0;
2124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pUnique->methods[nextMethod++] = pMethods[ii];
2126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid printMethodProfiles(TraceData* traceData, uint64_t sumThreadTime)
2130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii, jj;
2132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry* method;
2133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    double total, sum, per, sum_per;
2134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char classBuf[HTML_BUFSIZE], methodBuf[HTML_BUFSIZE];
2135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char signatureBuf[HTML_BUFSIZE];
2136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (traceData->numUniqueMethods == 0)
2138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
2139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    total = sumThreadTime;
2141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
2142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<a name=\"method\"></a>\n");
2143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<hr>\n");
2144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        outputNavigationBar();
2145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("\n%s\n", profileSeparator);
2147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("\nExclusive elapsed time for each method, summed over all the classes\n");
2150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("that contain a method with the same name.\n\n");
2151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
2152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<br><br>\n");
2153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* For each unique method, sum the exclusive times in all of the methods
2156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * with the same name.  Also sum the number of method calls.  Also
2157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * sort the methods so the most expensive appear at the top.
2158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UniqueMethodEntry *pUnique = traceData->uniqueMethods;
2160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < traceData->numUniqueMethods; ++ii, ++pUnique) {
2161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int numMethods = pUnique->numMethods;
2162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (jj = 0; jj < numMethods; ++jj) {
2163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method = pUnique->methods[jj];
2164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pUnique->elapsedExclusive += method->elapsedExclusive;
2165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pUnique->numCalls[0] += method->numCalls[0];
2166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pUnique->numCalls[1] += method->numCalls[1];
2167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Sort the methods into decreasing order of exclusive time */
2170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        qsort(pUnique->methods, numMethods, sizeof(MethodEntry*),
2171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project              compareElapsedExclusive);
2172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Allocate an array of pointers to the methods for more efficient
2175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * sorting.
2176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UniqueMethodEntry **pUniqueMethods;
2178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int nbytes = sizeof(UniqueMethodEntry*) * traceData->numUniqueMethods;
2179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pUniqueMethods = (UniqueMethodEntry**) malloc(nbytes);
2180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < traceData->numUniqueMethods; ++ii)
2181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pUniqueMethods[ii] = &traceData->uniqueMethods[ii];
2182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Sort the methods into decreasing order of exclusive time */
2184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(pUniqueMethods, traceData->numUniqueMethods, sizeof(UniqueMethodEntry*),
2185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project          compareUniqueExclusive);
2186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
2188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<div class=\"header\"><span class=\"parent\">&nbsp;</span>&nbsp;&nbsp;&nbsp;");
2189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("Cycles %%/total Cumul.%% &nbsp;Calls+Recur&nbsp; Method</div>\n");
2190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("   Cycles %%/total Cumul.%%  Calls+Recur  Method\n");
2192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sum = 0;
2195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < traceData->numUniqueMethods; ++ii) {
2196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char *className, *methodName, *signature;
2197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Skip methods with zero cycles */
2199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pUnique = pUniqueMethods[ii];
2200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pUnique->elapsedExclusive == 0)
2201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
2202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        per = 100.0 * pUnique->elapsedExclusive / total;
2204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sum += pUnique->elapsedExclusive;
2205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sum_per = 100.0 * sum / total;
2206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodName = (char*)(pUnique->methods[0]->methodName);
2207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) {
2208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            char buf[80];
2209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodName = htmlEscape(methodName, methodBuf, HTML_BUFSIZE);
2211f6c387128427e121477c1b32ad35cdcaa5101ba3The 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);
2212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "%llu", pUnique->elapsedExclusive);
2213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printHtmlField(buf, 9);
2214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" ");
2215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "%.1f", per);
2216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printHtmlField(buf, 7);
2217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" ");
2218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "%.1f", sum_per);
2219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printHtmlField(buf, 7);
2220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" ");
2221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "%d", pUnique->numCalls[0]);
2222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printHtmlField(buf, 6);
2223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("+");
2224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(buf, "%d", pUnique->numCalls[1]);
2225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printHtmlField(buf, -6);
2226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" ");
2227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("%s", methodName);
2228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("</div>\n");
2229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("<div class=\"parent\" id=\"e%d\">\n", ii);
2230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
2231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("---------------------------------------------\n");
2232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("%9llu %7.1f %7.1f %6d+%-6d %s\n",
2233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   pUnique->elapsedExclusive, per, sum_per,
2234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   pUnique->numCalls[0], pUnique->numCalls[1],
2235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   methodName);
2236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int numMethods = pUnique->numMethods;
2238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        double methodExclusive = pUnique->elapsedExclusive;
2239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        double sumMethods = 0;
2240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (jj = 0; jj < numMethods; ++jj) {
2241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method = pUnique->methods[jj];
2242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            className = (char*)(method->className);
2243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            signature = (char*)(method->signature);
2244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            per = 100.0 * method->elapsedExclusive / methodExclusive;
2245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sumMethods += method->elapsedExclusive;
2246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sum_per = 100.0 * sumMethods / methodExclusive;
2247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (gOptions.outputHtml) {
2248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                char buf[80];
2249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                className = htmlEscape(className, classBuf, HTML_BUFSIZE);
2251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                signature = htmlEscape(signature, signatureBuf, HTML_BUFSIZE);
2252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("<div class=\"leaf\"><span class=\"leaf\">&nbsp;</span>");
2253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%llu", method->elapsedExclusive);
2254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, 9);
2255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("&nbsp;");
2256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%llu", method->elapsedInclusive);
2257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, 9);
2258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("&nbsp;");
2259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%.1f", per);
2260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, 7);
2261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("&nbsp;");
2262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%.1f", sum_per);
2263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, 7);
2264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("&nbsp;");
2265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%d", method->numCalls[0]);
2266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, 6);
2267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("+");
2268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sprintf(buf, "%d", method->numCalls[1]);
2269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printHtmlField(buf, -6);
2270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("&nbsp;");
2271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("<a href=\"#m%d\">[%d]</a>&nbsp;%s.%s&nbsp;%s",
2272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       method->index, method->index,
2273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       className, methodName, signature);
2274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("</div>\n");
2275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
2276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf("%9llu %9llu %7.1f %7.1f %6d+%-6d [%d] %s.%s %s\n",
2277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       method->elapsedExclusive,
2278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       method->elapsedInclusive,
2279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       per, sum_per,
2280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       method->numCalls[0], method->numCalls[1],
2281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       method->index, className, methodName, signature);
2282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) {
2285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("</div>\n");
2286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Read the key and data files and return the MethodEntries for those files
2292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
22937b522639a499f63ccb5162576830d0c20539bd05Andy McFaddenDataKeys* parseDataKeys(TraceData* traceData, const char* traceFileName, uint64_t* threadTime)
2294de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro{
2295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DataKeys* dataKeys = NULL;
2296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry **pMethods = NULL;
2297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry* method;
2298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    FILE* dataFp = NULL;
2299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DataHeader dataHeader;
23007b522639a499f63ccb5162576830d0c20539bd05Andy McFadden    int ii;
2301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t currentTime;
2302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry* caller;
2303de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dataFp = fopen(traceFileName, "r");
2305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dataFp == NULL)
2306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((dataKeys = parseKeys(dataFp, 0)) == NULL)
23097b522639a499f63ccb5162576830d0c20539bd05Andy McFadden        goto bail;
2310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (parseDataHeader(dataFp, &dataHeader) < 0)
2312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
2315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    FILE *dumpStream = fopen("debug", "w");
2316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
2317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (1) {
2318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int threadId;
2319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int methodVal;
2320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int action;
2321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int methodId;
2322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        CallStack *pStack;
2323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
2324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Extract values from file.
2325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2326949c3ec207a7720fb47f7b3ca1f84dfcfd70aaa9Jeff Brown        if (readDataRecord(dataFp, &dataHeader, &threadId, &methodVal, &currentTime))
2327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
23286978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
2329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        action = METHOD_ACTION(methodVal);
2330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodId = METHOD_ID(methodVal);
2331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Get the call stack for this thread */
2333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pStack = traceData->stacks[threadId];
2334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* If there is no call stack yet for this thread, then allocate one */
2336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pStack == NULL) {
2337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pStack = malloc(sizeof(CallStack));
2338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pStack->top = 0;
2339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pStack->lastEventTime = currentTime;
2340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pStack->threadStartTime = currentTime;
2341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            traceData->stacks[threadId] = pStack;
2342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Lookup the current method */
2345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        method = lookupMethod(dataKeys, methodId);
2346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method == NULL)
2347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method = &dataKeys->methods[UNKNOWN_INDEX];
2348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
2350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method->methodName) {
23517b522639a499f63ccb5162576830d0c20539bd05Andy McFadden            fprintf(dumpStream, "%2d %-8llu %d %8llu r %d c %d %s.%s %s\n",
23527b522639a499f63ccb5162576830d0c20539bd05Andy McFadden                    threadId, currentTime, action, pStack->threadStartTime,
23537b522639a499f63ccb5162576830d0c20539bd05Andy McFadden                    method->recursiveEntries,
23547b522639a499f63ccb5162576830d0c20539bd05Andy McFadden                    pStack->top, method->className, method->methodName,
23557b522639a499f63ccb5162576830d0c20539bd05Andy McFadden                    method->signature);
2356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
23577b522639a499f63ccb5162576830d0c20539bd05Andy McFadden            fprintf(dumpStream, "%2d %-8llu %d %8llu r %d c %d %s\n",
23587b522639a499f63ccb5162576830d0c20539bd05Andy McFadden                    threadId, currentTime, action, pStack->threadStartTime,
23597b522639a499f63ccb5162576830d0c20539bd05Andy McFadden                    method->recursiveEntries,
23607b522639a499f63ccb5162576830d0c20539bd05Andy McFadden                    pStack->top, method->className);
2361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
2363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (action == METHOD_TRACE_ENTER) {
2365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* This is a method entry */
2366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (pStack->top >= MAX_STACK_DEPTH) {
2367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                fprintf(stderr, "Stack overflow (exceeded %d frames)\n",
2368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        MAX_STACK_DEPTH);
2369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                exit(1);
2370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Get the caller method */
2373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (pStack->top >= 1)
2374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                caller = pStack->calls[pStack->top - 1].method;
2375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            else
2376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                caller = &dataKeys->methods[TOPLEVEL_INDEX];
2377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            countRecursiveEntries(pStack, pStack->top, caller);
2378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            caller->elapsedExclusive += currentTime - pStack->lastEventTime;
2379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
2380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (caller->elapsedExclusive > 10000000)
2381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                fprintf(dumpStream, "%llu current %llu last %llu diff %llu\n",
2382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        caller->elapsedExclusive, currentTime,
2383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        pStack->lastEventTime,
2384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        currentTime - pStack->lastEventTime);
2385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
2386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (caller->recursiveEntries <= 1) {
2387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                caller->topExclusive += currentTime - pStack->lastEventTime;
2388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Push the method on the stack for this thread */
2391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pStack->calls[pStack->top].method = method;
2392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pStack->calls[pStack->top++].entryTime = currentTime;
2393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
2394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* This is a method exit */
2395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            uint64_t entryTime = 0;
2396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Pop the method off the stack for this thread */
2398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (pStack->top > 0) {
2399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pStack->top -= 1;
2400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                entryTime = pStack->calls[pStack->top].entryTime;
2401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (method != pStack->calls[pStack->top].method) {
2402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (method->methodName) {
2403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        fprintf(stderr,
2404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            "Exit from method %s.%s %s does not match stack:\n",
2405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            method->className, method->methodName,
2406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            method->signature);
2407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } else {
2408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        fprintf(stderr,
2409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            "Exit from method %s does not match stack:\n",
2410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            method->className);
2411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
2412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    stackDump(pStack, pStack->top + 1);
2413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    exit(1);
2414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Get the caller method */
2418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (pStack->top >= 1)
2419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                caller = pStack->calls[pStack->top - 1].method;
2420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            else
2421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                caller = &dataKeys->methods[TOPLEVEL_INDEX];
2422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            countRecursiveEntries(pStack, pStack->top, caller);
2423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            countRecursiveEntries(pStack, pStack->top, method);
2424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            uint64_t elapsed = currentTime - entryTime;
2425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            addInclusiveTime(caller, method, elapsed);
2426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->elapsedExclusive += currentTime - pStack->lastEventTime;
2427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (method->recursiveEntries == 0) {
2428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                method->topExclusive += currentTime - pStack->lastEventTime;
2429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Remember the time of the last entry or exit event */
2432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pStack->lastEventTime = currentTime;
2433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If we have calls on the stack when the trace ends, then clean
2436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * up the stack and add time to the callers by pretending that we
2437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * are exiting from their methods now.
2438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStack *pStack;
2440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int threadId;
2441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t sumThreadTime = 0;
2442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (threadId = 0; threadId < MAX_THREADS; ++threadId) {
2443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pStack = traceData->stacks[threadId];
2444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* If this thread never existed, then continue with next thread */
2446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pStack == NULL)
2447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
2448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
24497b522639a499f63ccb5162576830d0c20539bd05Andy McFadden        /* Also, add up the time taken by all of the threads */
24507b522639a499f63ccb5162576830d0c20539bd05Andy McFadden        sumThreadTime += pStack->lastEventTime - pStack->threadStartTime;
24515b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
2452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (ii = 0; ii < pStack->top; ++ii) {
2453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (ii == 0)
2454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                caller = &dataKeys->methods[TOPLEVEL_INDEX];
2455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            else
2456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                caller = pStack->calls[ii - 1].method;
2457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method = pStack->calls[ii].method;
2458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            countRecursiveEntries(pStack, ii, caller);
2459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            countRecursiveEntries(pStack, ii, method);
2460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            uint64_t entryTime = pStack->calls[ii].entryTime;
2462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            uint64_t elapsed = pStack->lastEventTime - entryTime;
2463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            addInclusiveTime(caller, method, elapsed);
2464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    caller = &dataKeys->methods[TOPLEVEL_INDEX];
2467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    caller->elapsedInclusive = sumThreadTime;
2468de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
2470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fclose(dumpStream);
2471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
2472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (threadTime != NULL) {
2474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *threadTime = sumThreadTime;
2475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
2478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dataFp != NULL)
2479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fclose(dataFp);
2480de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dataKeys;
2482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectMethodEntry** parseMethodEntries(DataKeys* dataKeys)
2485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii;
2487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Create a new array of pointers to the methods and sort the pointers
2488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * instead of the actual MethodEntry structs.  We need to do this
2489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * because there are other lists that contain pointers to the
2490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * MethodEntry structs.
2491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry** pMethods = (MethodEntry**) malloc(sizeof(MethodEntry*) * dataKeys->numMethods);
2493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < dataKeys->numMethods; ++ii) {
2494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        MethodEntry* entry = &dataKeys->methods[ii];
2495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pMethods[ii] = entry;
2496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2497de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return pMethods;
2499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Produce a function profile from the following methods
2503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
25047b522639a499f63ccb5162576830d0c20539bd05Andy McFaddenvoid profileTrace(TraceData* traceData, MethodEntry **pMethods, int numMethods, uint64_t sumThreadTime)
2505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
25067b522639a499f63ccb5162576830d0c20539bd05Andy McFadden    /* Print the html header, if necessary */
2507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
2508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(htmlHeader, gOptions.sortableUrl);
2509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        outputTableOfContents();
2510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printExclusiveProfile(pMethods, numMethods, sumThreadTime);
2513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printInclusiveProfile(pMethods, numMethods, sumThreadTime);
2514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    createClassList(traceData, pMethods, numMethods);
2516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printClassProfiles(traceData, sumThreadTime);
2517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    createUniqueMethodList(traceData, pMethods, numMethods);
2519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printMethodProfiles(traceData, sumThreadTime);
2520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
2522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%s", htmlFooter);
2523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint compareMethodNamesForDiff(const void *a, const void *b)
2527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
2529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const MethodEntry *methodA = *(const MethodEntry**)a;
2531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const MethodEntry *methodB = *(const MethodEntry**)b;
2532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (methodA->methodName == NULL || methodB->methodName == NULL) {
2533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return compareClassNames(a, b);
2534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = strcmp(methodA->methodName, methodB->methodName);
2536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result == 0) {
2537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = strcmp(methodA->signature, methodB->signature);
2538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result == 0) {
2539de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro           return strcmp(methodA->className, methodB->className);
2540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
2543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint findMatch(MethodEntry** methods, int size, MethodEntry* matchThis)
2546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
2548de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0 ; i < size ; i++) {
2550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        MethodEntry* method = methods[i];
2551de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (method != NULL && !compareMethodNamesForDiff(&method, &matchThis)) {
2553de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro//            printf("%s.%s == %s.%s<br>\n", matchThis->className, matchThis->methodName,
2554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project  //              method->className, method->methodName);
2555de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return i;
2557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*            if (!compareMethodNames(&method, &matchThis)) {
2558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return i;
2559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/        }
2561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2562de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return -1;
2564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint compareDiffEntriesExculsive(const void *a, const void *b)
2567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
2569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DiffEntry* entryA = (const DiffEntry*)a;
2571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DiffEntry* entryB = (const DiffEntry*)b;
2572de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (entryA->differenceExclusive < entryB->differenceExclusive) {
2574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
2575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else if (entryA->differenceExclusive > entryB->differenceExclusive) {
2576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
2577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2578de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
2580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint compareDiffEntriesInculsive(const void *a, const void *b)
2583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
2585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DiffEntry* entryA = (const DiffEntry*)a;
2587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DiffEntry* entryB = (const DiffEntry*)b;
2588de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (entryA->differenceInclusive < entryB->differenceInclusive) {
2590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
2591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else if (entryA->differenceInclusive > entryB->differenceInclusive) {
2592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
2593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2594de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
2596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2598de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapirovoid printMissingMethod(MethodEntry* method)
2599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char classBuf[HTML_BUFSIZE];
2601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char methodBuf[HTML_BUFSIZE];
2602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* className;
2603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* methodName;
2604de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    className = htmlEscape(method->className, classBuf, HTML_BUFSIZE);
2606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    methodName = htmlEscape(method->methodName, methodBuf, HTML_BUFSIZE);
2607de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2608de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro    if (gOptions.outputHtml) printf("<tr><td>\n");
2609de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("%s.%s ", className, methodName);
2611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) printf("</td><td>");
2612de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("%lld ", method->elapsedExclusive);
2614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) printf("</td><td>");
2615de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("%lld ", method->elapsedInclusive);
2617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) printf("</td><td>");
2618de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("%d\n", method->numCalls[0]);
2620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) printf("</td><td>\n");
2621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid createDiff(DataKeys* d1, uint64_t sum1, DataKeys* d2, uint64_t sum2)
2625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry** methods1 = parseMethodEntries(d1);
2627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MethodEntry** methods2 = parseMethodEntries(d2);
2628de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2629de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro    // sort and assign the indicies
2630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
2631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(methods1, d1->numMethods, sizeof(MethodEntry*), compareElapsedInclusive);
2632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < d1->numMethods; ++i) {
2633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methods1[i]->index = i;
2634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(methods2, d2->numMethods, sizeof(MethodEntry*), compareElapsedInclusive);
2637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < d2->numMethods; ++i) {
2638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methods2[i]->index = i;
2639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2640de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int max = (d1->numMethods < d2->numMethods) ? d2->numMethods : d1->numMethods;
2642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    max++;
2643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DiffEntry* diffs = (DiffEntry*)malloc(max * sizeof(DiffEntry));
2644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(diffs, 0, max * sizeof(DiffEntry));
2645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DiffEntry* ptr = diffs;
2646de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//    printf("<br>d1->numMethods: %d d1->numMethods: %d<br>\n", d1->numMethods, d2->numMethods);
2648de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int matches = 0;
2650de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0 ; i < d1->numMethods ; i++) {
2652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int match = findMatch(methods2, d2->numMethods, methods1[i]);
2653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (match >= 0) {
2654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ptr->method1 = methods1[i];
2655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ptr->method2 = methods2[match];
2656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            uint64_t e1 = ptr->method1->elapsedExclusive;
2658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            uint64_t e2 = ptr->method2->elapsedExclusive;
2659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (e1 > 0) {
2660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ptr->differenceExclusive = e2 - e1;
2661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ptr->differenceExclusivePercentage = ((double)e2 / (double)e1) * 100.0;
2662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            uint64_t i1 = ptr->method1->elapsedInclusive;
2665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            uint64_t i2 = ptr->method2->elapsedInclusive;
2666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (i1 > 0) {
2667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ptr->differenceInclusive = i2 - i1;
2668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ptr->differenceInclusivePercentage = ((double)i2 / (double)i1) * 100.0;
2669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2670de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // clear these out so we don't find them again and we know which ones
2672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // we have left over
2673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methods1[i] = NULL;
2674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methods2[match] = NULL;
2675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ptr++;
2676de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            matches++;
2678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ptr->method1 = NULL;
2681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ptr->method2 = NULL;
2682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(diffs, matches, sizeof(DiffEntry), compareDiffEntriesExculsive);
2684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ptr = diffs;
2685de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
2687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(htmlHeader, gOptions.sortableUrl);
2688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<h3>Table of Contents</h3>\n");
2689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<ul>\n");
2690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<li><a href='#exclusive'>Exclusive</a>\n");
2691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<li><a href='#inclusive'>Inclusive</a>\n");
2692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("</ul>\n");
2693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("Run 1: %s<br>\n", gOptions.diffFileName);
2694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("Run 2: %s<br>\n", gOptions.traceFileName);
2695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<a name=\"exclusive\"></a><h3 id=\"exclusive\">Exclusive</h3>\n");
2696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(tableHeader, "exclusive_table");
2697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2698de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char classBuf[HTML_BUFSIZE];
2700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char methodBuf[HTML_BUFSIZE];
2701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* className;
2702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* methodName;
2703de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (ptr->method1 != NULL && ptr->method2 != NULL) {
2705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("<tr><td>\n");
2706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        className = htmlEscape(ptr->method1->className, classBuf, HTML_BUFSIZE);
2708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodName = htmlEscape(ptr->method1->methodName, methodBuf, HTML_BUFSIZE);
2709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%s.%s ", className, methodName);
2711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>");
2712de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%lld ", ptr->method1->elapsedExclusive);
2714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>");
2715de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%llu ", ptr->method2->elapsedExclusive);
2717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>");
2718de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%lld ", ptr->differenceExclusive);
2720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>");
2721de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%.2f\n", ptr->differenceExclusivePercentage);
2723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>\n");
2724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%d\n", ptr->method1->numCalls[0]);
2726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>\n");
2727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%d\n", ptr->method2->numCalls[0]);
2729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td></tr>\n");
2730de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ptr++;
2732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2733de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) printf("</table>\n");
2735de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
2737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(htmlHeader, gOptions.sortableUrl);
2738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("Run 1: %s<br>\n", gOptions.diffFileName);
2739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("Run 2: %s<br>\n", gOptions.traceFileName);
2740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<a name=\"inclusive\"></a><h3 id=\"inculisve\">Inclusive</h3>\n");
2741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(tableHeader, "inclusive_table");
2742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2743de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    qsort(diffs, matches, sizeof(DiffEntry), compareDiffEntriesInculsive);
2745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ptr = diffs;
2746de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (ptr->method1 != NULL && ptr->method2 != NULL) {
2748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("<tr><td>\n");
2749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        className = htmlEscape(ptr->method1->className, classBuf, HTML_BUFSIZE);
2751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodName = htmlEscape(ptr->method1->methodName, methodBuf, HTML_BUFSIZE);
2752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%s.%s ", className, methodName);
2754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>");
2755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%lld ", ptr->method1->elapsedInclusive);
2757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>");
2758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%llu ", ptr->method2->elapsedInclusive);
2760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>");
2761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%lld ", ptr->differenceInclusive);
2763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>");
2764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%.2f\n", ptr->differenceInclusivePercentage);
2766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>\n");
2767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%d\n", ptr->method1->numCalls[0]);
2769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td><td>\n");
2770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("%d\n", ptr->method2->numCalls[0]);
2772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.outputHtml) printf("</td></tr>\n");
2773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ptr++;
2775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
2778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("</table>\n");
2779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<h3>Run 1 methods not found in Run 2</h3>");
27807b522639a499f63ccb5162576830d0c20539bd05Andy McFadden        printf(tableHeaderMissing, "?");
2781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2782de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < d1->numMethods; ++i) {
2784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methods1[i] != NULL) {
2785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project           printMissingMethod(methods1[i]);
2786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2788de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) {
2790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("</table>\n");
2791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("<h3>Run 2 methods not found in Run 1</h3>");
27927b522639a499f63ccb5162576830d0c20539bd05Andy McFadden        printf(tableHeaderMissing, "?");
2793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2794de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < d2->numMethods; ++i) {
2796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methods2[i] != NULL) {
2797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printMissingMethod(methods2[i]);
2798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2800de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.outputHtml) printf("</body></html\n");
2802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint usage(const char *program)
2805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
28067b522639a499f63ccb5162576830d0c20539bd05Andy McFadden    fprintf(stderr, "Copyright (C) 2006 The Android Open Source Project\n\n");
28077b522639a499f63ccb5162576830d0c20539bd05Andy McFadden    fprintf(stderr, "usage: %s [-ho] [-s sortable] [-d trace-file-name] [-g outfile] trace-file-name\n", program);
2808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, "  -d trace-file-name  - Diff with this trace\n");
2809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, "  -g outfile          - Write graph to 'outfile'\n");
2810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, "  -k                  - When writing a graph, keep the intermediate DOT file\n");
2811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, "  -h                  - Turn on HTML output\n");
2812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, "  -o                  - Dump the dmtrace file instead of profiling\n");
2813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, "  -s                  - URL base to where the sortable javascript file\n");
2814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, "  -t threshold        - Threshold percentage for including nodes in the graph\n");
2815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 2;
2816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// Returns true if there was an error
2819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint parseOptions(int argc, char **argv)
2820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (1) {
28227b522639a499f63ccb5162576830d0c20539bd05Andy McFadden        int opt = getopt(argc, argv, "d:hg:kos:t:");
2823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (opt == -1)
2824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
2825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (opt) {
2826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'd':
2827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                gOptions.diffFileName = optarg;
2828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
2829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'g':
2830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                gOptions.graphFileName = optarg;
2831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
2832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'k':
2833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                gOptions.keepDotFile = 1;
2834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
2835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'h':
2836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                gOptions.outputHtml = 1;
2837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
2838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'o':
2839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                gOptions.dump = 1;
2840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
2841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 's':
2842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                gOptions.sortableUrl = optarg;
2843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
2844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 't':
2845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                gOptions.threshold = atoi(optarg);
2846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
2847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default:
2848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return 1;
2849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
2852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parse args.
2856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint main(int argc, char** argv)
2858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gOptions.threshold = -1;
28606978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
2861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // Parse the options
2862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (parseOptions(argc, argv) || argc - optind != 1)
2863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return usage(argv[0]);
2864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gOptions.traceFileName = argv[optind];
2866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.threshold < 0 || 100 <= gOptions.threshold) {
2868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gOptions.threshold = 20;
2869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
28705b55af706cf3823494123da092a0a0319297a93eRodrigo Ipince
2871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.dump) {
2872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dumpTrace();
2873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 0;
2874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint64_t sumThreadTime = 0;
28776978d9dd28968b3817533d036ae7b53309053faaRodrigo Ipince
2878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    TraceData data1;
2879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DataKeys* dataKeys = parseDataKeys(&data1, gOptions.traceFileName,
28807b522639a499f63ccb5162576830d0c20539bd05Andy McFadden                                       &sumThreadTime);
2881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dataKeys == NULL) {
2882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr, "Cannot read trace.\n");
2883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        exit(1);
2884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.diffFileName != NULL) {
2887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        uint64_t sum2;
2888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        TraceData data2;
28897b522639a499f63ccb5162576830d0c20539bd05Andy McFadden        DataKeys* d2 = parseDataKeys(&data2, gOptions.diffFileName, &sum2);
2890de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        createDiff(d2, sum2, dataKeys, sumThreadTime);
2892de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        freeDataKeys(d2);
2894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        MethodEntry** methods = parseMethodEntries(dataKeys);
28967b522639a499f63ccb5162576830d0c20539bd05Andy McFadden        profileTrace(&data1, methods, dataKeys->numMethods, sumThreadTime);
2897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.graphFileName != NULL) {
2898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            createInclusiveProfileGraphNew(dataKeys);
2899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(methods);
2901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2902de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
2903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    freeDataKeys(dataKeys);
2904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
2906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2907