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 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 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 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 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 */