diff options
author | glider@chromium.org <glider@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-21 10:55:10 +0000 |
---|---|---|
committer | glider@chromium.org <glider@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-21 10:55:10 +0000 |
commit | 5eac6029cdecb6e15a014f8185f0bac5e118418f (patch) | |
tree | 4027035c21cc7b68c448805bc580a8197d499bb8 /third_party/tcmalloc/chromium/src/stacktrace_powerpc-inl.h | |
parent | 8741cfecae9a11360850b01e998cfbf9cc443f92 (diff) | |
download | chromium_src-5eac6029cdecb6e15a014f8185f0bac5e118418f.zip chromium_src-5eac6029cdecb6e15a014f8185f0bac5e118418f.tar.gz chromium_src-5eac6029cdecb6e15a014f8185f0bac5e118418f.tar.bz2 |
Revert 47789 - The newer version of tcmalloc should fix the problems with running tcmalloc under Valgrind.
Review URL: http://codereview.chromium.org/1735024
TBR=willchan,antonm
Review URL: http://codereview.chromium.org/2138002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@47909 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'third_party/tcmalloc/chromium/src/stacktrace_powerpc-inl.h')
-rw-r--r-- | third_party/tcmalloc/chromium/src/stacktrace_powerpc-inl.h | 115 |
1 files changed, 74 insertions, 41 deletions
diff --git a/third_party/tcmalloc/chromium/src/stacktrace_powerpc-inl.h b/third_party/tcmalloc/chromium/src/stacktrace_powerpc-inl.h index 9a07eea..5631e49 100644 --- a/third_party/tcmalloc/chromium/src/stacktrace_powerpc-inl.h +++ b/third_party/tcmalloc/chromium/src/stacktrace_powerpc-inl.h @@ -36,11 +36,6 @@ // http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK // Linux has similar code: http://patchwork.ozlabs.org/linuxppc/patch?id=8882 -#ifndef BASE_STACKTRACE_POWERPC_INL_H_ -#define BASE_STACKTRACE_POWERPC_INL_H_ -// Note: this file is included into stacktrace.cc more than once. -// Anything that should only be defined once should be here: - #include <stdint.h> // for uintptr_t #include <stdlib.h> // for NULL #include <google/stacktrace.h> @@ -76,23 +71,9 @@ static void **NextStackFrame(void **old_sp) { // This ensures that GetStackTrace stes up the Link Register properly. void StacktracePowerPCDummyFunction() __attribute__((noinline)); void StacktracePowerPCDummyFunction() { __asm__ volatile(""); } -#endif // BASE_STACKTRACE_POWERPC_INL_H_ - -// Note: this part of the file is included several times. -// Do not put globals below. -// The following 4 functions are generated from the code below: -// GetStack{Trace,Frames}() -// GetStack{Trace,Frames}WithContext() -// -// These functions take the following args: -// void** result: the stack-trace, as an array -// int* sizes: the size of each stack frame, as an array -// (GetStackFrames* only) -// int max_depth: the size of the result (and sizes) array(s) -// int skip_count: how many stack pointers to skip before storing in result -// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only) -int GET_STACK_TRACE_OR_FRAMES { +// If you change this function, also change GetStackFrames below. +int GetStackTrace(void** result, int max_depth, int skip_count) { void **sp; // Apple OS X uses an old version of gnu as -- both Darwin 7.9.0 (Panther) // and Darwin 8.8.1 (Tiger) use as 1.38. This means we have to use a @@ -114,29 +95,11 @@ int GET_STACK_TRACE_OR_FRAMES { // This routine forces the compiler (at least gcc) to push it anyway. StacktracePowerPCDummyFunction(); -#if IS_STACK_FRAMES - // Note we do *not* increment skip_count here for the SYSV ABI. If - // we did, the list of stack frames wouldn't properly match up with - // the list of return addresses. Note this means the top pc entry - // is probably bogus for linux/ppc (and other SYSV-ABI systems). -#else // The LR save area is used by the callee, so the top entry is bogus. skip_count++; -#endif int n = 0; while (sp && n < max_depth) { -#if IS_STACK_FRAMES - // The GetStackFrames routine is called when we are in some - // informational context (the failure signal handler for example). - // Use the non-strict unwinding rules to produce a stack trace - // that is as complete as possible (even if it contains a few bogus - // entries in some rare cases). - void **next_sp = NextStackFrame<false>(sp); -#else - void **next_sp = NextStackFrame<true>(sp); -#endif - if (skip_count > 0) { skip_count--; } else { @@ -157,15 +120,85 @@ int GET_STACK_TRACE_OR_FRAMES { #else #error Need to specify the PPC ABI for your archiecture. #endif + } + // Use strict unwinding rules. + sp = NextStackFrame<true>(sp); + } + return n; +} + +// If you change this function, also change GetStackTrace above: +// +// This GetStackFrames routine shares a lot of code with GetStackTrace +// above. This code could have been refactored into a common routine, +// and then both GetStackTrace/GetStackFrames could call that routine. +// There are two problems with that: +// +// (1) The performance of the refactored-code suffers substantially - the +// refactored needs to be able to record the stack trace when called +// from GetStackTrace, and both the stack trace and stack frame sizes, +// when called from GetStackFrames - this introduces enough new +// conditionals that GetStackTrace performance can degrade by as much +// as 50%. +// +// (2) Whether the refactored routine gets inlined into GetStackTrace and +// GetStackFrames depends on the compiler, and we can't guarantee the +// behavior either-way, even with "__attribute__ ((always_inline))" +// or "__attribute__ ((noinline))". But we need this guarantee or the +// frame counts may be off by one. +// +// Both (1) and (2) can be addressed without this code duplication, by +// clever use of template functions, and by defining GetStackTrace and +// GetStackFrames as macros that expand to these template functions. +// However, this approach comes with its own set of problems - namely, +// macros and preprocessor trouble - for example, if GetStackTrace +// and/or GetStackFrames is ever defined as a member functions in some +// class, we are in trouble. +int GetStackFrames(void** pcs, int *sizes, int max_depth, int skip_count) { + void **sp; +#ifdef __APPLE__ + __asm__ volatile ("mr %0,r1" : "=r" (sp)); +#else + __asm__ volatile ("mr %0,1" : "=r" (sp)); +#endif -#if IS_STACK_FRAME + StacktracePowerPCDummyFunction(); + // Note we do *not* increment skip_count here for the SYSV ABI. If + // we did, the list of stack frames wouldn't properly match up with + // the list of return addresses. Note this means the top pc entry + // is probably bogus for linux/ppc (and other SYSV-ABI systems). + + int n = 0; + while (sp && n < max_depth) { + // The GetStackFrames routine is called when we are in some + // informational context (the failure signal handler for example). + // Use the non-strict unwinding rules to produce a stack trace + // that is as complete as possible (even if it contains a few bogus + // entries in some rare cases). + void **next_sp = NextStackFrame<false>(sp); + if (skip_count > 0) { + skip_count--; + } else { +#if defined(_CALL_AIX) || defined(_CALL_DARWIN) + pcs[n++] = *(sp+2); +#elif defined(_CALL_SYSV) + pcs[n++] = *(sp+1); +#elif defined(__APPLE__) || (defined(__linux) && defined(__PPC64__)) + // This check is in case the compiler doesn't define _CALL_AIX/etc. + pcs[n++] = *(sp+2); +#elif defined(__linux) + // This check is in case the compiler doesn't define _CALL_SYSV. + pcs[n++] = *(sp+1); +#else +#error Need to specify the PPC ABI for your archiecture. +#endif if (next_sp > sp) { sizes[n] = (uintptr_t)next_sp - (uintptr_t)sp; } else { // A frame-size of 0 is used to indicate unknown frame size. sizes[n] = 0; } -#endif + n++; } sp = next_sp; } |