honkster-perftools.rb 0.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ diff --git a/Makefile.in b/Makefile.in
2
+ index c3bf409..c613939 100644
3
+ --- a/Makefile.in
4
+ +++ b/Makefile.in
5
+ @@ -1367,13 +1367,13 @@ AUTOMAKE = @AUTOMAKE@
6
+ AWK = @AWK@
7
+ CC = @CC@
8
+ CCDEPMODE = @CCDEPMODE@
9
+ -CFLAGS = @CFLAGS@ -DBUILD_FOR_RUBY -fPIC
10
+ +CFLAGS = @CFLAGS@ -DBUILD_FOR_RUBY -fPIC -O0 -ggdb
11
+ CPP = @CPP@
12
+ CPPFLAGS = @CPPFLAGS@
13
+ CXX = @CXX@
14
+ CXXCPP = @CXXCPP@
15
+ CXXDEPMODE = @CXXDEPMODE@
16
+ -CXXFLAGS = @CXXFLAGS@ -DBUILD_FOR_RUBY -fPIC
17
+ +CXXFLAGS = @CXXFLAGS@ -DBUILD_FOR_RUBY -fPIC -O0 -ggdb
18
+ CYGPATH_W = @CYGPATH_W@
19
+ DEFS = @DEFS@
20
+ DEPDIR = @DEPDIR@
@@ -0,0 +1,13 @@
1
+ diff --git a/src/profiledata.h b/src/profiledata.h
2
+ index ccdf96f..0517614 100644
3
+ --- a/src/profiledata.h
4
+ +++ b/src/profiledata.h
5
+ @@ -106,7 +106,7 @@ class ProfileData {
6
+ int frequency_; // Sample frequency.
7
+ };
8
+
9
+ - static const int kMaxStackDepth = 64; // Max stack depth stored in profile
10
+ + static const int kMaxStackDepth = 300; // Max stack depth stored in profile
11
+
12
+ ProfileData();
13
+ ~ProfileData();
@@ -0,0 +1,107 @@
1
+ diff --git a/src/profiledata.cc b/src/profiledata.cc
2
+ index e6240d9..b901ee8 100644
3
+ --- a/src/profiledata.cc
4
+ +++ b/src/profiledata.cc
5
+ @@ -198,6 +198,29 @@ static void DumpProcSelfMaps(int fd) {
6
+ }
7
+ }
8
+
9
+ +#ifdef BUILD_FOR_RUBY
10
+ +void ProfileData::GcMark(void (*mark)(VALUE)) {
11
+ + if (!enabled()) {
12
+ + return;
13
+ + }
14
+ +
15
+ + for (int b = 0; b < kBuckets; b++) {
16
+ + Bucket* bucket = &hash_[b];
17
+ + for (int a = 0; a < kAssociativity; a++) {
18
+ + if (bucket->entry[a].count > 0) {
19
+ + Entry e = bucket->entry[a];
20
+ + if (e.depth > 1)
21
+ + for (int n=0; n<e.depth; n+=3) {
22
+ + if (e.stack[n])
23
+ + mark(e.stack[n]);
24
+ + mark(e.stack[n+1]);
25
+ + }
26
+ + }
27
+ + }
28
+ + }
29
+ +}
30
+ +#endif
31
+ +
32
+ void ProfileData::Stop() {
33
+ if (!enabled()) {
34
+ return;
35
+ diff --git a/src/profiledata.h b/src/profiledata.h
36
+ index 67c463d..a68e12f 100644
37
+ --- a/src/profiledata.h
38
+ +++ b/src/profiledata.h
39
+ @@ -40,6 +40,12 @@
40
+ #ifndef BASE_PROFILEDATA_H_
41
+ #define BASE_PROFILEDATA_H_
42
+
43
+ +#ifdef BUILD_FOR_RUBY
44
+ +extern "C" {
45
+ + typedef unsigned long VALUE;
46
+ +}
47
+ +#endif
48
+ +
49
+ #include <config.h>
50
+ #include <time.h> // for time_t
51
+ #include <stdint.h>
52
+ @@ -141,6 +147,10 @@ class ProfileData {
53
+ // Get the current state of the data collector.
54
+ void GetCurrentState(State* state) const;
55
+
56
+ +#ifdef BUILD_FOR_RUBY
57
+ + void GcMark(void (*cb)(VALUE));
58
+ +#endif
59
+ +
60
+ private:
61
+ static const int kAssociativity = 4; // For hashtable
62
+ static const int kBuckets = 1 << 10; // For hashtable
63
+ diff --git a/src/profiler.cc b/src/profiler.cc
64
+ index d89a53a..37234b2 100644
65
+ --- a/src/profiler.cc
66
+ +++ b/src/profiler.cc
67
+ @@ -87,6 +87,10 @@ class CpuProfiler {
68
+ // Write the data to disk (and continue profiling).
69
+ void FlushTable();
70
+
71
+ +#ifdef BUILD_FOR_RUBY
72
+ + void GcMark(void (*cb)(VALUE));
73
+ +#endif
74
+ +
75
+ bool Enabled();
76
+
77
+ void GetCurrentState(ProfilerState* state);
78
+ @@ -221,6 +225,16 @@ void CpuProfiler::FlushTable() {
79
+ EnableHandler();
80
+ }
81
+
82
+ +#ifdef BUILD_FOR_RUBY
83
+ +void CpuProfiler::GcMark(void (*cb)(VALUE)) {
84
+ + if (!collector_.enabled()) {
85
+ + return;
86
+ + }
87
+ +
88
+ + collector_.GcMark(cb);
89
+ +}
90
+ +#endif
91
+ +
92
+ bool CpuProfiler::Enabled() {
93
+ SpinLockHolder cl(&lock_);
94
+ return collector_.enabled();
95
+ @@ -300,6 +314,12 @@ extern "C" PERFTOOLS_DLL_DECL void ProfilerFlush() {
96
+ CpuProfiler::instance_.FlushTable();
97
+ }
98
+
99
+ +#ifdef BUILD_FOR_RUBY
100
+ +extern "C" PERFTOOLS_DLL_DECL void ProfilerGcMark(void (*cb)(VALUE)) {
101
+ + CpuProfiler::instance_.GcMark(cb);
102
+ +}
103
+ +#endif
104
+ +
105
+ extern "C" PERFTOOLS_DLL_DECL int ProfilingIsEnabledForAllThreads() {
106
+ return CpuProfiler::instance_.Enabled();
107
+ }
@@ -0,0 +1,15 @@
1
+ diff --git a/Makefile.in b/Makefile.in
2
+ index b301f4d..969db5e 100644
3
+ --- a/Makefile.in
4
+ +++ b/Makefile.in
5
+ @@ -65,9 +65,7 @@ host_triplet = @host@
6
+ @ENABLE_FRAME_POINTERS_TRUE@@X86_64_AND_NO_FP_BY_DEFAULT_TRUE@am__append_3 = -fno-omit-frame-pointer
7
+ @ENABLE_FRAME_POINTERS_FALSE@@X86_64_AND_NO_FP_BY_DEFAULT_TRUE@am__append_4 = -DNO_FRAME_POINTER
8
+ @MINGW_TRUE@am__append_5 = -Wl,-u__tcmalloc
9
+ -noinst_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
10
+ - $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \
11
+ - $(am__EXEEXT_7) $(am__EXEEXT_8) $(am__EXEEXT_23)
12
+ +noinst_PROGRAMS =
13
+ bin_PROGRAMS =
14
+ @MINGW_TRUE@am__append_6 = libwindows.la libspinlock.la
15
+
@@ -0,0 +1,85 @@
1
+ diff --git a/src/profile-handler.cc b/src/profile-handler.cc
2
+ index 5df5054..2335617 100644
3
+ --- a/src/profile-handler.cc
4
+ +++ b/src/profile-handler.cc
5
+ @@ -395,6 +395,8 @@ void ProfileHandler::GetState(ProfileHandlerState* state) {
6
+ }
7
+
8
+ void ProfileHandler::StartTimer() {
9
+ + if (getenv("CPUPROFILE_OBJECTS") || getenv("CPUPROFILE_METHODS")) return;
10
+ +
11
+ struct itimerval timer;
12
+ timer.it_interval.tv_sec = 0;
13
+ timer.it_interval.tv_usec = 1000000 / frequency_;
14
+ @@ -403,12 +405,16 @@ void ProfileHandler::StartTimer() {
15
+ }
16
+
17
+ void ProfileHandler::StopTimer() {
18
+ + if (getenv("CPUPROFILE_OBJECTS") || getenv("CPUPROFILE_METHODS")) return;
19
+ +
20
+ struct itimerval timer;
21
+ memset(&timer, 0, sizeof timer);
22
+ setitimer(timer_type_, &timer, 0);
23
+ }
24
+
25
+ bool ProfileHandler::IsTimerRunning() {
26
+ + if (getenv("CPUPROFILE_OBJECTS") || getenv("CPUPROFILE_METHODS")) return false;
27
+ +
28
+ struct itimerval current_timer;
29
+ RAW_CHECK(0 == getitimer(timer_type_, &current_timer), "getitimer");
30
+ return (current_timer.it_value.tv_sec != 0 ||
31
+ @@ -416,6 +422,8 @@ bool ProfileHandler::IsTimerRunning() {
32
+ }
33
+
34
+ void ProfileHandler::EnableHandler() {
35
+ + if (getenv("CPUPROFILE_OBJECTS") || getenv("CPUPROFILE_METHODS")) return;
36
+ +
37
+ struct sigaction sa;
38
+ sa.sa_sigaction = SignalHandler;
39
+ sa.sa_flags = SA_RESTART | SA_SIGINFO;
40
+ @@ -425,6 +433,8 @@ void ProfileHandler::EnableHandler() {
41
+ }
42
+
43
+ void ProfileHandler::DisableHandler() {
44
+ + if (getenv("CPUPROFILE_OBJECTS") || getenv("CPUPROFILE_METHODS")) return;
45
+ +
46
+ struct sigaction sa;
47
+ sa.sa_handler = SIG_IGN;
48
+ sa.sa_flags = SA_RESTART;
49
+ diff --git a/src/profiler.cc b/src/profiler.cc
50
+ index f408cf8..7645c45 100644
51
+ --- a/src/profiler.cc
52
+ +++ b/src/profiler.cc
53
+ @@ -102,6 +102,10 @@ class CpuProfiler {
54
+
55
+ static CpuProfiler instance_;
56
+
57
+ + // Signal handler that records the interrupted pc in the profile data.
58
+ + static void prof_handler(int sig, siginfo_t*, void* signal_ucontext,
59
+ + void* cpu_profiler);
60
+ +
61
+ private:
62
+ // This lock implements the locking requirements described in the ProfileData
63
+ // documentation, specifically:
64
+ @@ -130,10 +134,6 @@ class CpuProfiler {
65
+
66
+ // Disables receiving SIGPROF interrupt.
67
+ void DisableHandler();
68
+ -
69
+ - // Signal handler that records the interrupted pc in the profile data.
70
+ - static void prof_handler(int sig, siginfo_t*, void* signal_ucontext,
71
+ - void* cpu_profiler);
72
+ };
73
+
74
+ // Profile data structure singleton: Constructor will check to see if
75
+ @@ -323,6 +323,10 @@ extern "C" PERFTOOLS_DLL_DECL void ProfilerFlush() {
76
+ extern "C" PERFTOOLS_DLL_DECL void ProfilerGcMark(void (*cb)(VALUE)) {
77
+ CpuProfiler::instance_.GcMark(cb);
78
+ }
79
+ +
80
+ +extern "C" PERFTOOLS_DLL_DECL void ProfilerRecord(int sig, siginfo_t* info, void* signal_ucontext) {
81
+ + CpuProfiler::prof_handler(sig, info, signal_ucontext, (void*)&CpuProfiler::instance_);
82
+ +}
83
+ #endif
84
+
85
+ extern "C" PERFTOOLS_DLL_DECL int ProfilingIsEnabledForAllThreads() {
@@ -0,0 +1,13 @@
1
+ diff --git a/Makefile.in b/Makefile.in
2
+ index 566d77c..c3bf409 100644
3
+ --- a/Makefile.in
4
+ +++ b/Makefile.in
5
+ @@ -1397,7 +1397,7 @@ INSTALL_DATA = @INSTALL_DATA@
6
+ INSTALL_PROGRAM = @INSTALL_PROGRAM@
7
+ INSTALL_SCRIPT = @INSTALL_SCRIPT@
8
+ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
9
+ -LDFLAGS = @LDFLAGS@
10
+ +LDFLAGS = @LDFLAGS@ -Wl,-flat_namespace,-undefined,dynamic_lookup
11
+ LIBOBJS = @LIBOBJS@
12
+ LIBS = @LIBS@
13
+ LIBSTDCXX_LA_LINKER_FLAG = @LIBSTDCXX_LA_LINKER_FLAG@
@@ -0,0 +1,76 @@
1
+ commit 1828f461a3ea523b7018d03ab83850621cf66ba9
2
+ Author: Aman Gupta <aman@tmm1.net>
3
+ Date: Fri Nov 12 16:33:15 2010 -0600
4
+
5
+ perftools-pprof
6
+
7
+ diff --git a/src/pprof b/src/pprof
8
+ index e67e42e..b04d988 100755
9
+ --- a/src/pprof
10
+ +++ b/src/pprof
11
+ @@ -560,7 +560,8 @@ sub Main() {
12
+ my $symbol_map = {};
13
+
14
+ # Read one profile, pick the last item on the list
15
+ - my $data = ReadProfile($main::prog, pop(@main::profile_files));
16
+ + my $fname = pop(@main::profile_files);
17
+ + my $data = ReadProfile($main::prog, $fname);
18
+ my $profile = $data->{profile};
19
+ my $pcs = $data->{pcs};
20
+ my $libs = $data->{libs}; # Info about main program and shared libraries
21
+ @@ -589,7 +590,18 @@ sub Main() {
22
+
23
+ # Collect symbols
24
+ my $symbols;
25
+ - if ($main::use_symbolized_profile) {
26
+ + if (-e "$fname.symbols") {
27
+ + open(SYMBOLS, "<$fname.symbols");
28
+ + while(<SYMBOLS>){
29
+ + chop;
30
+ + if (m/(.+?)\s*:\s*(.*)/){
31
+ + $symbols->{$1}[0] = $2;
32
+ + $symbols->{$1}[1] = "?";
33
+ + $symbols->{$1}[2] = $2;
34
+ + }
35
+ + }
36
+ + close(SYMBOLS);
37
+ + } elsif ($main::use_symbolized_profile) {
38
+ $symbols = FetchSymbols($pcs, $symbol_map);
39
+ } elsif ($main::use_symbol_page) {
40
+ $symbols = FetchSymbols($pcs);
41
+ @@ -2425,6 +2437,10 @@ sub RemoveUninterestingFrames {
42
+ foreach my $name ('ProfileData::Add', # historical
43
+ 'ProfileData::prof_handler', # historical
44
+ 'CpuProfiler::prof_handler',
45
+ + 'PerfTools::CpuProfiler.start',
46
+ + 'Array#each',
47
+ + 'Proc#call',
48
+ + 'Class#new',
49
+ '__FRAME_END__',
50
+ '__pthread_sighandler',
51
+ '__restore') {
52
+ @@ -2434,6 +2450,7 @@ sub RemoveUninterestingFrames {
53
+ # Nothing skipped for unknown types
54
+ }
55
+
56
+ +=pod
57
+ if ($main::profile_type eq 'cpu') {
58
+ # If all the second-youngest program counters are the same,
59
+ # this STRONGLY suggests that it is an artifact of measurement,
60
+ @@ -2458,6 +2475,7 @@ sub RemoveUninterestingFrames {
61
+ $profile = $result;
62
+ }
63
+ }
64
+ +=cut
65
+
66
+ my $result = {};
67
+ foreach my $k (keys(%{$profile})) {
68
+ @@ -3360,7 +3378,7 @@ sub ReadCPUProfile {
69
+ # file, in which case the subtract-one was done when the file
70
+ # was written.
71
+ if ($j > 0 && !$main::use_symbolized_profile) {
72
+ - $pc--;
73
+ + # $pc--;
74
+ }
75
+ $pc = sprintf("%0*x", $address_length, $pc);
76
+ $pcs->{$pc} = 1;
@@ -0,0 +1,34 @@
1
+ Only in ./: perftools-stddef.patch
2
+ diff -ru .//src/base/vdso_support.h ../google-perftools-1.6-patched/src/base/vdso_support.h
3
+ --- .//src/base/vdso_support.h 2010-08-03 03:32:20.000000000 +0800
4
+ +++ ../google-perftools-1.6-patched/src/base/vdso_support.h 2011-06-16 14:33:10.000000000 +0800
5
+ @@ -38,6 +38,7 @@
6
+ #define HAVE_VDSO_SUPPORT 1
7
+
8
+ #include <stdlib.h> // for NULL
9
+ +#include <stddef.h>
10
+ #include <link.h> // for ElfW
11
+ #include "base/basictypes.h"
12
+
13
+ diff -ru .//src/symbolize.h ../google-perftools-1.6-patched/src/symbolize.h
14
+ --- .//src/symbolize.h 2009-11-11 03:59:46.000000000 +0800
15
+ +++ ../google-perftools-1.6-patched/src/symbolize.h 2011-06-16 14:32:55.000000000 +0800
16
+ @@ -38,6 +38,7 @@
17
+ #include <stdint.h> // for uintptr_t
18
+ #endif
19
+ #include <map>
20
+ +#include <stddef.h>
21
+
22
+ using std::map;
23
+
24
+ diff -ru .//src/system-alloc.h ../google-perftools-1.6-patched/src/system-alloc.h
25
+ --- .//src/system-alloc.h 2010-04-01 07:50:18.000000000 +0800
26
+ +++ ../google-perftools-1.6-patched/src/system-alloc.h 2011-06-16 14:32:38.000000000 +0800
27
+ @@ -38,6 +38,7 @@
28
+
29
+ #include <config.h>
30
+ #include "internal_logging.h"
31
+ +#include <stddef.h>
32
+
33
+ // REQUIRES: "alignment" is a power of two or "0" to indicate default alignment
34
+ //
@@ -0,0 +1,266 @@
1
+ diff --git a/Makefile.in b/Makefile.in
2
+ index 232d2ec..566d77c 100644
3
+ --- a/Makefile.in
4
+ +++ b/Makefile.in
5
+ @@ -1367,13 +1367,13 @@ AUTOMAKE = @AUTOMAKE@
6
+ AWK = @AWK@
7
+ CC = @CC@
8
+ CCDEPMODE = @CCDEPMODE@
9
+ -CFLAGS = @CFLAGS@
10
+ +CFLAGS = @CFLAGS@ -DBUILD_FOR_RUBY -fPIC
11
+ CPP = @CPP@
12
+ CPPFLAGS = @CPPFLAGS@
13
+ CXX = @CXX@
14
+ CXXCPP = @CXXCPP@
15
+ CXXDEPMODE = @CXXDEPMODE@
16
+ -CXXFLAGS = @CXXFLAGS@
17
+ +CXXFLAGS = @CXXFLAGS@ -DBUILD_FOR_RUBY -fPIC
18
+ CYGPATH_W = @CYGPATH_W@
19
+ DEFS = @DEFS@
20
+ DEPDIR = @DEPDIR@
21
+ diff --git a/src/profile-handler.cc b/src/profile-handler.cc
22
+ index e658d30..370d012 100644
23
+ --- a/src/profile-handler.cc
24
+ +++ b/src/profile-handler.cc
25
+ @@ -264,6 +264,11 @@ ProfileHandler::~ProfileHandler() {
26
+ void ProfileHandler::RegisterThread() {
27
+ SpinLockHolder cl(&control_lock_);
28
+
29
+ +#ifdef BUILD_FOR_RUBY
30
+ + timer_sharing_ = TIMERS_SHARED;
31
+ + if (callback_count_ > 0 && !IsTimerRunning())
32
+ + StartTimer();
33
+ +#else
34
+ // We try to detect whether timers are being shared by setting a
35
+ // timer in the first call to this function, then checking whether
36
+ // it's set in the second call.
37
+ @@ -305,6 +310,7 @@ void ProfileHandler::RegisterThread() {
38
+ StartTimer();
39
+ break;
40
+ }
41
+ +#endif
42
+ }
43
+
44
+ ProfileHandlerToken* ProfileHandler::RegisterCallback(
45
+ diff --git a/src/profiledata.cc b/src/profiledata.cc
46
+ index 5f2531b..ea95493 100644
47
+ --- a/src/profiledata.cc
48
+ +++ b/src/profiledata.cc
49
+ @@ -56,6 +56,19 @@ const int ProfileData::kAssociativity;
50
+ const int ProfileData::kBuckets;
51
+ const int ProfileData::kBufferLength;
52
+
53
+ +#ifdef BUILD_FOR_RUBY
54
+ +extern "C" {
55
+ + typedef unsigned long ID;
56
+ + typedef unsigned long VALUE;
57
+ +
58
+ + void rb_gc();
59
+ + const char *rb_id2name(ID);
60
+ + const char *rb_class2name(VALUE);
61
+ +}
62
+ +
63
+ +#include <set>
64
+ +#endif
65
+ +
66
+ ProfileData::Options::Options()
67
+ : frequency_(1) {
68
+ }
69
+ @@ -63,17 +76,33 @@ ProfileData::Options::Options()
70
+ // This function is safe to call from asynchronous signals (but is not
71
+ // re-entrant). However, that's not part of its public interface.
72
+ void ProfileData::Evict(const Entry& entry) {
73
+ +#ifdef BUILD_FOR_RUBY
74
+ + const int d = entry.depth == 1 ? 1 : entry.depth/3;
75
+ +#else
76
+ const int d = entry.depth;
77
+ +#endif
78
+ const int nslots = d + 2; // Number of slots needed in eviction buffer
79
+ +
80
+ if (num_evicted_ + nslots > kBufferLength) {
81
+ FlushEvicted();
82
+ assert(num_evicted_ == 0);
83
+ assert(nslots <= kBufferLength);
84
+ }
85
+ +
86
+ evict_[num_evicted_++] = entry.count;
87
+ evict_[num_evicted_++] = d;
88
+ +
89
+ +#ifdef BUILD_FOR_RUBY
90
+ + if (entry.depth > 1) {
91
+ + for (int n=0; n<entry.depth; n+=3)
92
+ + evict_[num_evicted_++] = entry.stack[n] + entry.stack[n+1] + entry.stack[n+2];
93
+ + } else if (entry.depth == 1) {
94
+ + evict_[num_evicted_++] = entry.stack[0];
95
+ + }
96
+ +#else
97
+ memcpy(&evict_[num_evicted_], entry.stack, d * sizeof(Slot));
98
+ num_evicted_ += d;
99
+ +#endif
100
+ }
101
+
102
+ ProfileData::ProfileData()
103
+ @@ -85,6 +114,7 @@ ProfileData::ProfileData()
104
+ evictions_(0),
105
+ total_bytes_(0),
106
+ fname_(0),
107
+ + sym_fname_(0),
108
+ start_time_(0) {
109
+ }
110
+
111
+ @@ -101,6 +131,13 @@ bool ProfileData::Start(const char* fname,
112
+ return false;
113
+ }
114
+
115
+ +#ifdef BUILD_FOR_RUBY
116
+ + int len = strlen(fname);
117
+ + sym_fname_ = (char*)malloc((len+9) * sizeof(char));
118
+ + strncpy(sym_fname_, fname, len);
119
+ + strcpy(sym_fname_+len, ".symbols");
120
+ +#endif
121
+ +
122
+ start_time_ = time(NULL);
123
+ fname_ = strdup(fname);
124
+
125
+ @@ -166,16 +203,61 @@ void ProfileData::Stop() {
126
+ return;
127
+ }
128
+
129
+ +#ifdef BUILD_FOR_RUBY
130
+ + FILE *symbols;
131
+ + int precision;
132
+ +
133
+ + symbols = fopen(sym_fname_, "w");
134
+ + if (!symbols) {
135
+ + fprintf(stderr, "PROFILER ERROR: Unable to open %s (%s)\n", sym_fname_, strerror(errno));
136
+ + Reset();
137
+ + return;
138
+ + }
139
+ +
140
+ + precision = sizeof(unsigned long)*2;
141
+ + fprintf(symbols, "%0*lx: garbage_collector\n", precision, (ID)rb_gc);
142
+ +
143
+ + std::set<ID> known_symbols;
144
+ +#endif
145
+ +
146
+ // Move data from hash table to eviction buffer
147
+ for (int b = 0; b < kBuckets; b++) {
148
+ Bucket* bucket = &hash_[b];
149
+ for (int a = 0; a < kAssociativity; a++) {
150
+ if (bucket->entry[a].count > 0) {
151
+ - Evict(bucket->entry[a]);
152
+ + Entry e = bucket->entry[a];
153
+ + Evict(e);
154
+ +#ifdef BUILD_FOR_RUBY
155
+ + if (e.depth > 1) {
156
+ + for (int n=0; n<e.depth; n+=3) {
157
+ + VALUE self = e.stack[n];
158
+ + VALUE klass = e.stack[n+1];
159
+ + ID method = e.stack[n+2];
160
+ +
161
+ + ID sym = self + klass + method; // unique identifer
162
+ +
163
+ + if (known_symbols.find(sym) == known_symbols.end()) {
164
+ + fprintf(symbols, "%0*lx: ", precision, sym);
165
+ +
166
+ + if (self) { // class method
167
+ + fprintf(symbols, "%s.%s\n", rb_class2name(self), rb_id2name(method));
168
+ + } else { // instance method
169
+ + fprintf(symbols, "%s#%s\n", rb_class2name(klass), rb_id2name(method));
170
+ + }
171
+ +
172
+ + known_symbols.insert(sym);
173
+ + }
174
+ + }
175
+ + }
176
+ +#endif
177
+ }
178
+ }
179
+ }
180
+
181
+ +#ifdef BUILD_FOR_RUBY
182
+ + fclose(symbols);
183
+ +#endif
184
+ +
185
+ if (num_evicted_ + 3 > kBufferLength) {
186
+ // Ensure there is enough room for end of data marker
187
+ FlushEvicted();
188
+ @@ -211,6 +293,10 @@ void ProfileData::Reset() {
189
+ num_evicted_ = 0;
190
+ free(fname_);
191
+ fname_ = 0;
192
+ +#ifdef BUILD_FOR_RUBY
193
+ + free(sym_fname_);
194
+ + sym_fname_ = 0;
195
+ +#endif
196
+ start_time_ = 0;
197
+
198
+ out_ = -1;
199
+ diff --git a/src/profiledata.h b/src/profiledata.h
200
+ index da7ea9e..67c463d 100644
201
+ --- a/src/profiledata.h
202
+ +++ b/src/profiledata.h
203
+ @@ -169,6 +169,7 @@ class ProfileData {
204
+ int evictions_; // How many evictions
205
+ size_t total_bytes_; // How much output
206
+ char* fname_; // Profile file name
207
+ + char* sym_fname_; // Symbol file name
208
+ time_t start_time_; // Start time, or 0
209
+
210
+ // Move 'entry' to the eviction buffer.
211
+ diff --git a/src/profiler.cc b/src/profiler.cc
212
+ index 183a7c7..d89a53a 100644
213
+ --- a/src/profiler.cc
214
+ +++ b/src/profiler.cc
215
+ @@ -63,6 +63,12 @@ typedef int ucontext_t; // just to quiet the compiler, mostly
216
+ #include "conflict-signal.h" /* used on msvc machines */
217
+ #endif
218
+
219
+ +#ifdef BUILD_FOR_RUBY
220
+ +extern "C" {
221
+ + int rb_stack_trace(void**,int);
222
+ +}
223
+ +#endif
224
+ +
225
+ using std::string;
226
+
227
+ // Collects up all profile data. This is a singleton, which is
228
+ @@ -261,6 +267,9 @@ void CpuProfiler::prof_handler(int sig, siginfo_t*, void* signal_ucontext,
229
+ (*instance->filter_)(instance->filter_arg_)) {
230
+ void* stack[ProfileData::kMaxStackDepth];
231
+
232
+ +#ifdef BUILD_FOR_RUBY
233
+ + int depth = rb_stack_trace(stack, arraysize(stack));
234
+ +#else
235
+ // The top-most active routine doesn't show up as a normal
236
+ // frame, but as the "pc" value in the signal handler context.
237
+ stack[0] = GetPC(*reinterpret_cast<ucontext_t*>(signal_ucontext));
238
+ @@ -274,8 +283,10 @@ void CpuProfiler::prof_handler(int sig, siginfo_t*, void* signal_ucontext,
239
+ int depth = GetStackTraceWithContext(stack + 1, arraysize(stack) - 1,
240
+ 2, signal_ucontext);
241
+ depth++; // To account for pc value in stack[0];
242
+ +#endif
243
+
244
+ - instance->collector_.Add(depth, stack);
245
+ + if (depth > 0)
246
+ + instance->collector_.Add(depth, stack);
247
+ }
248
+ }
249
+
250
+ diff --git a/src/stacktrace.cc b/src/stacktrace.cc
251
+ index d158eea..e8509fe 100644
252
+ --- a/src/stacktrace.cc
253
+ +++ b/src/stacktrace.cc
254
+ @@ -52,6 +52,7 @@
255
+ // correctly when GetStackTrace() is called with max_depth == 0.
256
+ // Some code may do that.
257
+
258
+ +#ifndef BUILD_FOR_RUBY
259
+ #include <config.h>
260
+ #include <google/stacktrace.h>
261
+ #include "stacktrace_config.h"
262
+ @@ -69,3 +70,4 @@
263
+ #else
264
+ # error Cannot calculate stack trace: will need to write for your environment
265
+ #endif
266
+ +#endif