1 /* Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6
7 /* XRay -- a simple profiler for Native Client */
8
9 #ifndef XRAY_DISABLE_BROWSER_INTEGRATION
10
11 #include <alloca.h>
12 #include <assert.h>
13 #include <errno.h>
14 #include <stdarg.h>
15 #include <stdint.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <unistd.h>
20 #include "ppapi/c/dev/ppb_trace_event_dev.h"
21 #include "xray/xray_priv.h"
22
23
24 #if defined(XRAY)
25 static PPB_Trace_Event_Dev* ppb_trace_event_interface = NULL;
26
XRayGetName(struct XRaySymbolTable * symbols,struct XRayTraceBufferEntry * e)27 static const char* XRayGetName(struct XRaySymbolTable* symbols,
28 struct XRayTraceBufferEntry* e) {
29 uint32_t addr = XRAY_EXTRACT_ADDR(e->depth_addr);
30 struct XRaySymbol* symbol = XRaySymbolTableLookup(symbols, addr);
31 return XRaySymbolGetName(symbol);
32 }
33
XRayGenerateTimestampsNow(void)34 struct XRayTimestampPair XRayGenerateTimestampsNow(void) {
35 struct XRayTimestampPair pair;
36 assert(ppb_trace_event_interface);
37
38 XRayGetTSC(&pair.xray);
39 pair.pepper = ppb_trace_event_interface->Now();
40 return pair;
41 }
42
43 /* see chromium/src/base/debug/trace_event.h */
44 #define TRACE_VALUE_TYPE_UINT (2)
45 #define TRACE_VALUE_TYPE_DOUBLE (4)
46 #define TRACE_VALUE_TYPE_COPY_STRING (7)
47
48 union TraceValue {
49 bool as_bool;
50 unsigned long long as_uint;
51 long long as_int;
52 double as_double;
53 const void* as_pointer;
54 const char* as_string;
55 };
56
XRayBrowserTraceReport(struct XRayTraceCapture * capture)57 void XRayBrowserTraceReport(struct XRayTraceCapture* capture) {
58
59 const void* cat_enabled = ppb_trace_event_interface->GetCategoryEnabled(
60 "xray");
61 struct XRaySymbolTable* symbols = XRayGetSymbolTable(capture);
62
63 int32_t thread_id = XRayGetSavedThreadID(capture);
64
65 int head = XRayFrameGetHead(capture);
66 int frame = XRayFrameGetTail(capture);
67 while(frame != head) {
68
69 struct XRayTimestampPair start_time = XRayFrameGetStartTimestampPair(
70 capture, frame);
71 struct XRayTimestampPair end_time = XRayFrameGetEndTimestampPair(
72 capture, frame);
73
74 double pdiff = (end_time.pepper - start_time.pepper);
75 double odiff = (end_time.xray - start_time.xray);
76 double scale_a = pdiff / odiff;
77 double scale_b = ((double)end_time.pepper) - (scale_a * end_time.xray);
78 printf("Xray timestamp calibration frame %d: %f %f\n",
79 frame, scale_a, scale_b);
80
81 int start = XRayFrameGetTraceStartIndex(capture, frame);
82 int end = XRayFrameGetTraceEndIndex(capture, frame);
83
84 struct XRayTraceBufferEntry** stack_base = XRayMalloc(
85 sizeof(struct XRayTraceBufferEntry*) * (XRAY_TRACE_STACK_SIZE + 1));
86 struct XRayTraceBufferEntry** stack_top = stack_base;
87 *stack_top = NULL;
88
89 uint32_t num_args = 0;
90 const char* arg_names[] = {"annotation"};
91 uint8_t arg_types[] = {TRACE_VALUE_TYPE_COPY_STRING};
92 uint64_t arg_values[] = {0};
93 char annotation[XRAY_TRACE_ANNOTATION_LENGTH];
94
95 int i;
96 for(i = start; i != end; i = XRayTraceNextEntry(capture, i)) {
97 if (XRayTraceIsAnnotation(capture, i)) {
98 continue;
99 }
100
101 uint32_t depth = XRAY_EXTRACT_DEPTH(
102 XRayTraceGetEntry(capture, i)->depth_addr);
103
104 while(*stack_top &&
105 XRAY_EXTRACT_DEPTH((*stack_top)->depth_addr) >= depth) {
106 struct XRayTraceBufferEntry* e = *(stack_top--);
107 ppb_trace_event_interface->AddTraceEventWithThreadIdAndTimestamp(
108 'E', cat_enabled,
109 XRayGetName(symbols, e),
110 0, thread_id,
111 (scale_a * e->end_tick) + scale_b,
112 0, NULL, NULL, NULL, 0
113 );
114 }
115
116 num_args = 0;
117 struct XRayTraceBufferEntry* e = XRayTraceGetEntry(capture, i);
118 uint32_t annotation_index = e->annotation_index;
119 if (annotation_index) {
120 XRayTraceCopyToString(capture, annotation_index, annotation);
121
122 union TraceValue val;
123 val.as_string = (const char*)annotation;
124
125 arg_values[0] = val.as_uint;
126 num_args = 1;
127 }
128
129 ppb_trace_event_interface->AddTraceEventWithThreadIdAndTimestamp(
130 'B', cat_enabled,
131 XRayGetName(symbols, e),
132 0, thread_id,
133 (scale_a * e->start_tick) + scale_b,
134 num_args, arg_names, arg_types, arg_values, 0
135 );
136
137 *(++stack_top) = e;
138 }
139
140 while(*stack_top) {
141 struct XRayTraceBufferEntry* e = *(stack_top--);
142 ppb_trace_event_interface->AddTraceEventWithThreadIdAndTimestamp(
143 'E', cat_enabled,
144 XRayGetName(symbols, e),
145 0, thread_id,
146 (scale_a * e->end_tick) + scale_b,
147 0, NULL, NULL, NULL, 0
148 );
149 }
150
151 frame = XRayFrameGetNext(capture, frame);
152 XRayFree(stack_base);
153 }
154 }
155
XRayRegisterBrowserInterface(PPB_GetInterface interface)156 void XRayRegisterBrowserInterface(PPB_GetInterface interface) {
157 ppb_trace_event_interface = (PPB_Trace_Event_Dev*)interface(
158 PPB_TRACE_EVENT_DEV_INTERFACE);
159 assert(ppb_trace_event_interface);
160 }
161
162 #endif /* XRAY */
163 #endif /* XRAY_DISABLE_BROWSER_INTEGRATION */