| /* Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| |
| /* XRay -- a simple profiler for Native Client */ |
| |
| #ifndef XRAY_DISABLE_BROWSER_INTEGRATION |
| |
| #include <alloca.h> |
| #include <assert.h> |
| #include <errno.h> |
| #include <stdarg.h> |
| #include <stdint.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include "ppapi/c/dev/ppb_trace_event_dev.h" |
| #include "xray/xray_priv.h" |
| |
| |
| #if defined(XRAY) |
| static PPB_Trace_Event_Dev* ppb_trace_event_interface = NULL; |
| |
| static const char* XRayGetName(struct XRaySymbolTable* symbols, |
| struct XRayTraceBufferEntry* e) { |
| uint32_t addr = XRAY_EXTRACT_ADDR(e->depth_addr); |
| struct XRaySymbol* symbol = XRaySymbolTableLookup(symbols, addr); |
| return XRaySymbolGetName(symbol); |
| } |
| |
| struct XRayTimestampPair XRayGenerateTimestampsNow(void) { |
| struct XRayTimestampPair pair; |
| assert(ppb_trace_event_interface); |
| |
| XRayGetTSC(&pair.xray); |
| pair.pepper = ppb_trace_event_interface->Now(); |
| return pair; |
| } |
| |
| /* see chromium/src/base/trace_event/trace_event.h */ |
| #define TRACE_VALUE_TYPE_UINT (2) |
| #define TRACE_VALUE_TYPE_DOUBLE (4) |
| #define TRACE_VALUE_TYPE_COPY_STRING (7) |
| |
| union TraceValue { |
| bool as_bool; |
| unsigned long long as_uint; |
| long long as_int; |
| double as_double; |
| const void* as_pointer; |
| const char* as_string; |
| }; |
| |
| void XRayBrowserTraceReport(struct XRayTraceCapture* capture) { |
| |
| const void* cat_enabled = ppb_trace_event_interface->GetCategoryEnabled( |
| "xray"); |
| struct XRaySymbolTable* symbols = XRayGetSymbolTable(capture); |
| |
| int32_t thread_id = XRayGetSavedThreadID(capture); |
| |
| int head = XRayFrameGetHead(capture); |
| int frame = XRayFrameGetTail(capture); |
| while(frame != head) { |
| |
| struct XRayTimestampPair start_time = XRayFrameGetStartTimestampPair( |
| capture, frame); |
| struct XRayTimestampPair end_time = XRayFrameGetEndTimestampPair( |
| capture, frame); |
| |
| double pdiff = (end_time.pepper - start_time.pepper); |
| double odiff = (end_time.xray - start_time.xray); |
| double scale_a = pdiff / odiff; |
| double scale_b = ((double)end_time.pepper) - (scale_a * end_time.xray); |
| printf("Xray timestamp calibration frame %d: %f %f\n", |
| frame, scale_a, scale_b); |
| |
| int start = XRayFrameGetTraceStartIndex(capture, frame); |
| int end = XRayFrameGetTraceEndIndex(capture, frame); |
| |
| struct XRayTraceBufferEntry** stack_base = XRayMalloc( |
| sizeof(struct XRayTraceBufferEntry*) * (XRAY_TRACE_STACK_SIZE + 1)); |
| struct XRayTraceBufferEntry** stack_top = stack_base; |
| *stack_top = NULL; |
| |
| uint32_t num_args = 0; |
| const char* arg_names[] = {"annotation"}; |
| uint8_t arg_types[] = {TRACE_VALUE_TYPE_COPY_STRING}; |
| uint64_t arg_values[] = {0}; |
| char annotation[XRAY_TRACE_ANNOTATION_LENGTH]; |
| |
| int i; |
| for(i = start; i != end; i = XRayTraceNextEntry(capture, i)) { |
| if (XRayTraceIsAnnotation(capture, i)) { |
| continue; |
| } |
| |
| uint32_t depth = XRAY_EXTRACT_DEPTH( |
| XRayTraceGetEntry(capture, i)->depth_addr); |
| |
| while(*stack_top && |
| XRAY_EXTRACT_DEPTH((*stack_top)->depth_addr) >= depth) { |
| struct XRayTraceBufferEntry* e = *(stack_top--); |
| ppb_trace_event_interface->AddTraceEventWithThreadIdAndTimestamp( |
| 'E', cat_enabled, |
| XRayGetName(symbols, e), |
| 0, thread_id, |
| (scale_a * e->end_tick) + scale_b, |
| 0, NULL, NULL, NULL, 0 |
| ); |
| } |
| |
| num_args = 0; |
| struct XRayTraceBufferEntry* e = XRayTraceGetEntry(capture, i); |
| uint32_t annotation_index = e->annotation_index; |
| if (annotation_index) { |
| XRayTraceCopyToString(capture, annotation_index, annotation); |
| |
| union TraceValue val; |
| val.as_string = (const char*)annotation; |
| |
| arg_values[0] = val.as_uint; |
| num_args = 1; |
| } |
| |
| ppb_trace_event_interface->AddTraceEventWithThreadIdAndTimestamp( |
| 'B', cat_enabled, |
| XRayGetName(symbols, e), |
| 0, thread_id, |
| (scale_a * e->start_tick) + scale_b, |
| num_args, arg_names, arg_types, arg_values, 0 |
| ); |
| |
| *(++stack_top) = e; |
| } |
| |
| while(*stack_top) { |
| struct XRayTraceBufferEntry* e = *(stack_top--); |
| ppb_trace_event_interface->AddTraceEventWithThreadIdAndTimestamp( |
| 'E', cat_enabled, |
| XRayGetName(symbols, e), |
| 0, thread_id, |
| (scale_a * e->end_tick) + scale_b, |
| 0, NULL, NULL, NULL, 0 |
| ); |
| } |
| |
| frame = XRayFrameGetNext(capture, frame); |
| XRayFree(stack_base); |
| } |
| } |
| |
| void XRayRegisterBrowserInterface(PPB_GetInterface interface) { |
| ppb_trace_event_interface = (PPB_Trace_Event_Dev*)interface( |
| PPB_TRACE_EVENT_DEV_INTERFACE); |
| assert(ppb_trace_event_interface); |
| } |
| |
| #endif /* XRAY */ |
| #endif /* XRAY_DISABLE_BROWSER_INTEGRATION */ |