• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */