Bug 766579 - Part 2: Intertwine during sampling. r=jmuizelaar

--HG--
extra : rebase_source : e2ddcc188fcd6a2b3b6c35d3517fb7ec8ae7deab
This commit is contained in:
Benoit Girard 2012-06-27 19:04:58 -04:00
parent 325b77e999
commit c8f0c7a400
3 changed files with 67 additions and 27 deletions

View File

@ -561,6 +561,33 @@ JSObject* TableTicker::ToJSObject(JSContext *aCx)
return profile;
}
static
void addProfileEntry(ProfileStack *aStack, ThreadProfile &aProfile, int i)
{
// First entry has tagName 's' (start)
// Check for magic pointer bit 1 to indicate copy
const char* sampleLabel = aStack->mStack[i].mLabel;
if (aStack->mStack[i].isCopyLabel()) {
// Store the string using 1 or more 'd' (dynamic) tags
// that will happen to the preceding tag
aProfile.addTag(ProfileEntry('c', ""));
// Add one to store the null termination
size_t strLen = strlen(sampleLabel) + 1;
for (size_t j = 0; j < strLen;) {
// Store as many characters in the void* as the platform allows
char text[sizeof(void*)];
for (size_t pos = 0; pos < sizeof(void*) && j+pos < strLen; pos++) {
text[pos] = sampleLabel[j+pos];
}
j += sizeof(void*)/sizeof(char);
// Cast to *((void**) to pass the text data to a void*
aProfile.addTag(ProfileEntry('d', *((void**)(&text[0]))));
}
} else {
aProfile.addTag(ProfileEntry('c', sampleLabel));
}
}
#ifdef USE_BACKTRACE
void TableTicker::doBacktrace(ThreadProfile &aProfile, TickSample* aSample)
@ -581,6 +608,7 @@ void TableTicker::doBacktrace(ThreadProfile &aProfile, TickSample* aSample)
#ifdef USE_NS_STACKWALK
typedef struct {
void** array;
void** sp_array;
size_t size;
size_t count;
} PCArray;
@ -593,7 +621,9 @@ void StackWalkCallback(void* aPC, void* aSP, void* aClosure)
// too many frames, ignore
return;
}
array->array[array->count++] = aPC;
array->sp_array[array->count] = aSP;
array->array[array->count] = aPC;
array->count++;
}
void TableTicker::doBacktrace(ThreadProfile &aProfile, TickSample* aSample)
@ -603,8 +633,10 @@ void TableTicker::doBacktrace(ThreadProfile &aProfile, TickSample* aSample)
MOZ_ASSERT(thread);
#endif
void* pc_array[1000];
void* sp_array[1000];
PCArray array = {
pc_array,
sp_array,
mozilla::ArrayLength(pc_array),
0
};
@ -624,8 +656,39 @@ void TableTicker::doBacktrace(ThreadProfile &aProfile, TickSample* aSample)
if (NS_SUCCEEDED(rv)) {
aProfile.addTag(ProfileEntry('s', "(root)"));
ProfileStack* stack = aProfile.GetStack();
int pseudoStackPos = 0;
/* We have two stacks, the native C stack we extracted from unwinding,
* and the pseudostack we managed during execution. We want to consolidate
* the two in order. We do so by merging using the approximate stack address
* when each entry was push. When pushing JS entry we may not now the stack
* address in which case we have a NULL stack address in which case we assume
* that it follows immediatly the previous element.
*
* C Stack | Address -- Pseudo Stack | Address
* main() | 0x100 run_js() | 0x40
* start() | 0x80 jsCanvas() | NULL
* timer() | 0x50 drawLine() | NULL
* azure() | 0x10
*
* Merged: main(), start(), timer(), run_js(), jsCanvas(), drawLine(), azure()
*/
// i is the index in C stack starting at main and decreasing
// pseudoStackPos is the position in the Pseudo stack starting
// at the first frame (run_js in the example) and increasing.
for (size_t i = array.count; i > 0; --i) {
aProfile.addTag(ProfileEntry('l', (void*)array.array[i - 1]));
while (pseudoStackPos < stack->mStackPointer) {
volatile StackEntry& entry = stack->mStack[pseudoStackPos];
if (entry.mStackAddress < array.sp_array[i-1] && entry.mStackAddress)
break;
addProfileEntry(stack, aProfile, pseudoStackPos);
pseudoStackPos++;
}
aProfile.addTag(ProfileEntry('l', (void*)array.array[i-1]));
}
}
}
@ -689,29 +752,7 @@ void doSampleStackTrace(ProfileStack *aStack, ThreadProfile &aProfile, TickSampl
for (mozilla::sig_safe_t i = 0;
i < aStack->mStackPointer && i < mozilla::ArrayLength(aStack->mStack);
i++) {
// First entry has tagName 's' (start)
// Check for magic pointer bit 1 to indicate copy
const char* sampleLabel = aStack->mStack[i].mLabel;
if (aStack->mStack[i].isCopyLabel()) {
// Store the string using 1 or more 'd' (dynamic) tags
// that will happen to the preceding tag
aProfile.addTag(ProfileEntry('c', ""));
// Add one to store the null termination
size_t strLen = strlen(sampleLabel) + 1;
for (size_t j = 0; j < strLen;) {
// Store as many characters in the void* as the platform allows
char text[sizeof(void*)];
for (size_t pos = 0; pos < sizeof(void*) && j+pos < strLen; pos++) {
text[pos] = sampleLabel[j+pos];
}
j += sizeof(void*);
// Take '*((void**)(&text[0]))' to pass the char[] as a single void*
aProfile.addTag(ProfileEntry('d', *((void**)(&text[0]))));
}
} else {
aProfile.addTag(ProfileEntry('c', sampleLabel));
}
addProfileEntry(aStack, aProfile, i);
}
#ifdef ENABLE_SPS_LEAF_DATA
if (sample) {

View File

@ -44,7 +44,6 @@
* application is responding to the event loop. Lower is better.
* 't' - Elapse time since recording started.
*
* NOTE: File format is planned to be extended to include a dictionary to reduce size.
*/
#ifndef SAMPLER_H

View File

@ -155,7 +155,7 @@ class NS_STACK_CLASS SamplerStackFrameRAII {
public:
// we only copy the strings at save time, so to take multiple parameters we'd need to copy them then.
SamplerStackFrameRAII(const char *aInfo) {
mHandle = mozilla_sampler_call_enter(aInfo);
mHandle = mozilla_sampler_call_enter(aInfo, this, false);
}
~SamplerStackFrameRAII() {
mozilla_sampler_call_exit(mHandle);