ruby-prof 1.1.0-x64-mingw32 → 1.3.0-x64-mingw32
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.
- checksums.yaml +4 -4
- data/CHANGES +19 -1
- data/bin/ruby-prof +100 -152
- data/ext/ruby_prof/rp_aggregate_call_tree.c +59 -0
- data/ext/ruby_prof/rp_aggregate_call_tree.h +13 -0
- data/ext/ruby_prof/rp_allocation.c +67 -59
- data/ext/ruby_prof/rp_allocation.h +3 -3
- data/ext/ruby_prof/rp_call_tree.c +369 -0
- data/ext/ruby_prof/rp_call_tree.h +43 -0
- data/ext/ruby_prof/rp_call_trees.c +288 -0
- data/ext/ruby_prof/rp_call_trees.h +28 -0
- data/ext/ruby_prof/rp_measure_allocations.c +11 -13
- data/ext/ruby_prof/rp_measure_process_time.c +11 -13
- data/ext/ruby_prof/rp_measure_wall_time.c +17 -15
- data/ext/ruby_prof/rp_measurement.c +47 -40
- data/ext/ruby_prof/rp_measurement.h +7 -7
- data/ext/ruby_prof/rp_method.c +116 -255
- data/ext/ruby_prof/rp_method.h +31 -39
- data/ext/ruby_prof/rp_profile.c +311 -281
- data/ext/ruby_prof/rp_profile.h +1 -2
- data/ext/ruby_prof/rp_stack.c +113 -105
- data/ext/ruby_prof/rp_stack.h +17 -20
- data/ext/ruby_prof/rp_thread.c +136 -111
- data/ext/ruby_prof/rp_thread.h +12 -9
- data/ext/ruby_prof/ruby_prof.c +27 -23
- data/ext/ruby_prof/ruby_prof.h +9 -0
- data/ext/ruby_prof/vc/ruby_prof.vcxproj +11 -7
- data/lib/ruby-prof.rb +2 -3
- data/lib/ruby-prof/assets/call_stack_printer.html.erb +4 -7
- data/lib/ruby-prof/assets/graph_printer.html.erb +5 -6
- data/lib/ruby-prof/{call_info.rb → call_tree.rb} +6 -6
- data/lib/ruby-prof/call_tree_visitor.rb +36 -0
- data/lib/ruby-prof/measurement.rb +5 -2
- data/lib/ruby-prof/method_info.rb +3 -15
- data/lib/ruby-prof/printers/call_info_printer.rb +12 -10
- data/lib/ruby-prof/printers/call_stack_printer.rb +19 -22
- data/lib/ruby-prof/printers/call_tree_printer.rb +1 -1
- data/lib/ruby-prof/printers/dot_printer.rb +3 -3
- data/lib/ruby-prof/printers/graph_printer.rb +3 -4
- data/lib/ruby-prof/printers/multi_printer.rb +2 -2
- data/lib/ruby-prof/rack.rb +3 -0
- data/lib/ruby-prof/thread.rb +3 -18
- data/lib/ruby-prof/version.rb +1 -1
- data/ruby-prof.gemspec +7 -0
- data/test/alias_test.rb +42 -45
- data/test/basic_test.rb +0 -86
- data/test/{call_info_visitor_test.rb → call_tree_visitor_test.rb} +6 -5
- data/test/call_trees_test.rb +66 -0
- data/test/exclude_methods_test.rb +17 -12
- data/test/fiber_test.rb +197 -9
- data/test/gc_test.rb +36 -42
- data/test/inverse_call_tree_test.rb +175 -0
- data/test/line_number_test.rb +67 -70
- data/test/marshal_test.rb +7 -11
- data/test/measure_allocations_test.rb +224 -234
- data/test/measure_allocations_trace_test.rb +224 -234
- data/test/measure_memory_trace_test.rb +814 -469
- data/test/measure_process_time_test.rb +0 -64
- data/test/measure_times.rb +2 -0
- data/test/measure_wall_time_test.rb +34 -58
- data/test/pause_resume_test.rb +19 -10
- data/test/prime.rb +1 -3
- data/test/prime_script.rb +6 -0
- data/test/printers_test.rb +1 -1
- data/test/recursive_test.rb +50 -54
- data/test/start_stop_test.rb +19 -19
- data/test/test_helper.rb +3 -15
- data/test/thread_test.rb +11 -11
- data/test/unique_call_path_test.rb +25 -95
- metadata +19 -10
- data/ext/ruby_prof/rp_call_info.c +0 -271
- data/ext/ruby_prof/rp_call_info.h +0 -35
- data/lib/2.6.5/ruby_prof.so +0 -0
- data/lib/ruby-prof/call_info_visitor.rb +0 -38
- data/test/parser_timings.rb +0 -24
| @@ -0,0 +1,28 @@ | |
| 1 | 
            +
            /* Copyright (C) 2005-2013 Shugo Maeda <shugo@ruby-lang.org> and Charlie Savage <cfis@savagexi.com>
         | 
| 2 | 
            +
               Please see the LICENSE file for copyright and distribution information */
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            #ifndef __RP_CALL_TREES_H__
         | 
| 5 | 
            +
            #define __RP_CALL_TREES_H__
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            #include "ruby_prof.h"
         | 
| 8 | 
            +
            #include "rp_call_tree.h"
         | 
| 9 | 
            +
             | 
| 10 | 
            +
               /* Array of call_tree objects */
         | 
| 11 | 
            +
            typedef struct prof_call_trees_t
         | 
| 12 | 
            +
            {
         | 
| 13 | 
            +
                prof_call_tree_t** start;
         | 
| 14 | 
            +
                prof_call_tree_t** end;
         | 
| 15 | 
            +
                prof_call_tree_t** ptr;
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                VALUE object;
         | 
| 18 | 
            +
            } prof_call_trees_t;
         | 
| 19 | 
            +
             | 
| 20 | 
            +
             | 
| 21 | 
            +
            void rp_init_call_trees();
         | 
| 22 | 
            +
            prof_call_trees_t* prof_call_trees_create();
         | 
| 23 | 
            +
            void prof_call_trees_free(prof_call_trees_t* call_trees);
         | 
| 24 | 
            +
            prof_call_trees_t* prof_get_call_trees(VALUE self);
         | 
| 25 | 
            +
            void prof_add_call_tree(prof_call_trees_t* call_trees, prof_call_tree_t* call_tree);
         | 
| 26 | 
            +
            VALUE prof_call_trees_wrap(prof_call_trees_t* call_trees);
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            #endif //__RP_CALL_TREES_H__
         | 
| @@ -8,14 +8,12 @@ | |
| 8 8 | 
             
            static VALUE cMeasureAllocations;
         | 
| 9 9 | 
             
            VALUE total_allocated_objects_key;
         | 
| 10 10 |  | 
| 11 | 
            -
            static double
         | 
| 12 | 
            -
            measure_allocations_via_gc_stats(rb_trace_arg_t* trace_arg)
         | 
| 11 | 
            +
            static double measure_allocations_via_gc_stats(rb_trace_arg_t* trace_arg)
         | 
| 13 12 | 
             
            {
         | 
| 14 13 | 
             
                return rb_gc_stat(total_allocated_objects_key);
         | 
| 15 14 | 
             
            }
         | 
| 16 15 |  | 
| 17 | 
            -
            static double
         | 
| 18 | 
            -
            measure_allocations_via_tracing(rb_trace_arg_t* trace_arg)
         | 
| 16 | 
            +
            static double measure_allocations_via_tracing(rb_trace_arg_t* trace_arg)
         | 
| 19 17 | 
             
            {
         | 
| 20 18 | 
             
                static double result = 0;
         | 
| 21 19 |  | 
| @@ -30,17 +28,17 @@ measure_allocations_via_tracing(rb_trace_arg_t* trace_arg) | |
| 30 28 |  | 
| 31 29 | 
             
            prof_measurer_t* prof_measurer_allocations(bool track_allocations)
         | 
| 32 30 | 
             
            {
         | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 31 | 
            +
                prof_measurer_t* measure = ALLOC(prof_measurer_t);
         | 
| 32 | 
            +
                measure->mode = MEASURE_ALLOCATIONS;
         | 
| 33 | 
            +
                measure->multiplier = 1;
         | 
| 34 | 
            +
                measure->track_allocations = track_allocations;
         | 
| 37 35 |  | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 36 | 
            +
                if (track_allocations)
         | 
| 37 | 
            +
                    measure->measure = measure_allocations_via_tracing;
         | 
| 38 | 
            +
                else
         | 
| 39 | 
            +
                    measure->measure = measure_allocations_via_gc_stats;
         | 
| 42 40 |  | 
| 43 | 
            -
             | 
| 41 | 
            +
                return measure;
         | 
| 44 42 | 
             
            }
         | 
| 45 43 |  | 
| 46 44 | 
             
            void rp_init_measure_allocations()
         | 
| @@ -6,8 +6,7 @@ | |
| 6 6 |  | 
| 7 7 | 
             
            static VALUE cMeasureProcessTime;
         | 
| 8 8 |  | 
| 9 | 
            -
            static double
         | 
| 10 | 
            -
            measure_process_time(rb_trace_arg_t* trace_arg)
         | 
| 9 | 
            +
            static double measure_process_time(rb_trace_arg_t* trace_arg)
         | 
| 11 10 | 
             
            {
         | 
| 12 11 | 
             
            #if defined(_WIN32)
         | 
| 13 12 | 
             
                FILETIME  createTime;
         | 
| @@ -29,16 +28,15 @@ measure_process_time(rb_trace_arg_t* trace_arg) | |
| 29 28 | 
             
            #elif !defined(CLOCK_PROCESS_CPUTIME_ID)
         | 
| 30 29 | 
             
                struct rusage usage;
         | 
| 31 30 | 
             
                getrusage(RUSAGE_SELF, &usage);
         | 
| 32 | 
            -
                return usage.ru_stime.tv_sec + usage.ru_utime.tv_sec + ((usage.ru_stime.tv_usec + usage.ru_utime.tv_usec)/1000000.0);
         | 
| 31 | 
            +
                return usage.ru_stime.tv_sec + usage.ru_utime.tv_sec + ((usage.ru_stime.tv_usec + usage.ru_utime.tv_usec) / 1000000.0);
         | 
| 33 32 | 
             
            #else
         | 
| 34 33 | 
             
                struct timespec clock;
         | 
| 35 | 
            -
                clock_gettime(CLOCK_PROCESS_CPUTIME_ID | 
| 36 | 
            -
                return clock.tv_sec + (clock.tv_nsec/1000000000.0);
         | 
| 34 | 
            +
                clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &clock);
         | 
| 35 | 
            +
                return clock.tv_sec + (clock.tv_nsec / 1000000000.0);
         | 
| 37 36 | 
             
            #endif
         | 
| 38 37 | 
             
            }
         | 
| 39 38 |  | 
| 40 | 
            -
            static double
         | 
| 41 | 
            -
            multiplier_process_time(void)
         | 
| 39 | 
            +
            static double multiplier_process_time(void)
         | 
| 42 40 | 
             
            {
         | 
| 43 41 | 
             
            #if defined(_WIN32)
         | 
| 44 42 | 
             
                // Times are in 100-nanosecond time units.  So instead of 10-9 use 10-7
         | 
| @@ -50,12 +48,12 @@ multiplier_process_time(void) | |
| 50 48 |  | 
| 51 49 | 
             
            prof_measurer_t* prof_measurer_process_time(bool track_allocations)
         | 
| 52 50 | 
             
            {
         | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 51 | 
            +
                prof_measurer_t* measure = ALLOC(prof_measurer_t);
         | 
| 52 | 
            +
                measure->mode = MEASURE_PROCESS_TIME;
         | 
| 53 | 
            +
                measure->measure = measure_process_time;
         | 
| 54 | 
            +
                measure->multiplier = multiplier_process_time();
         | 
| 55 | 
            +
                measure->track_allocations = track_allocations;
         | 
| 56 | 
            +
                return measure;
         | 
| 59 57 | 
             
            }
         | 
| 60 58 |  | 
| 61 59 | 
             
            void rp_init_measure_process_time()
         | 
| @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            /* Copyright (C) 2005-2019 Shugo Maeda <shugo@ruby-lang.org> and Charlie Savage <cfis@savagexi.com>
         | 
| 2 2 | 
             
               Please see the LICENSE file for copyright and distribution information */
         | 
| 3 3 |  | 
| 4 | 
            -
            /* :nodoc: */
         | 
| 4 | 
            +
               /* :nodoc: */
         | 
| 5 5 | 
             
            #include "rp_measurement.h"
         | 
| 6 6 |  | 
| 7 7 | 
             
            #if defined(__APPLE__)
         | 
| @@ -12,11 +12,12 @@ | |
| 12 12 |  | 
| 13 13 | 
             
            static VALUE cMeasureWallTime;
         | 
| 14 14 |  | 
| 15 | 
            -
            static double
         | 
| 16 | 
            -
            measure_wall_time(rb_trace_arg_t* trace_arg)
         | 
| 15 | 
            +
            static double measure_wall_time(rb_trace_arg_t* trace_arg)
         | 
| 17 16 | 
             
            {
         | 
| 18 17 | 
             
            #if defined(_WIN32)
         | 
| 19 | 
            -
                 | 
| 18 | 
            +
                LARGE_INTEGER time;
         | 
| 19 | 
            +
                QueryPerformanceCounter(&time);
         | 
| 20 | 
            +
                return time.QuadPart;
         | 
| 20 21 | 
             
            #elif defined(__APPLE__)
         | 
| 21 22 | 
             
                return mach_absolute_time();// * (uint64_t)mach_timebase.numer / (uint64_t)mach_timebase.denom;
         | 
| 22 23 | 
             
            #elif defined(__linux__)
         | 
| @@ -26,18 +27,19 @@ measure_wall_time(rb_trace_arg_t* trace_arg) | |
| 26 27 | 
             
            #else
         | 
| 27 28 | 
             
                struct timeval tv;
         | 
| 28 29 | 
             
                gettimeofday(&tv, NULL);
         | 
| 29 | 
            -
                return tv.tv_sec + (tv.tv_usec / 1000000.0); | 
| 30 | 
            +
                return tv.tv_sec + (tv.tv_usec / 1000000.0);
         | 
| 30 31 | 
             
            #endif
         | 
| 31 32 | 
             
            }
         | 
| 32 33 |  | 
| 33 | 
            -
            static double
         | 
| 34 | 
            -
            multiplier_wall_time(void)
         | 
| 34 | 
            +
            static double multiplier_wall_time(void)
         | 
| 35 35 | 
             
            {
         | 
| 36 36 | 
             
            #if defined(_WIN32)
         | 
| 37 | 
            -
                 | 
| 37 | 
            +
                LARGE_INTEGER frequency;
         | 
| 38 | 
            +
                QueryPerformanceFrequency(&frequency);
         | 
| 39 | 
            +
                return 1.0 / frequency.QuadPart;
         | 
| 38 40 | 
             
            #elif defined(__APPLE__)
         | 
| 39 41 | 
             
                mach_timebase_info_data_t mach_timebase;
         | 
| 40 | 
            -
                mach_timebase_info | 
| 42 | 
            +
                mach_timebase_info(&mach_timebase);
         | 
| 41 43 | 
             
                return (uint64_t)mach_timebase.numer / (uint64_t)mach_timebase.denom / 1000000000.0;
         | 
| 42 44 | 
             
            #else
         | 
| 43 45 | 
             
                return 1.0;
         | 
| @@ -46,12 +48,12 @@ multiplier_wall_time(void) | |
| 46 48 |  | 
| 47 49 | 
             
            prof_measurer_t* prof_measurer_wall_time(bool track_allocations)
         | 
| 48 50 | 
             
            {
         | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 51 | 
            +
                prof_measurer_t* measure = ALLOC(prof_measurer_t);
         | 
| 52 | 
            +
                measure->mode = MEASURE_WALL_TIME;
         | 
| 53 | 
            +
                measure->measure = measure_wall_time;
         | 
| 54 | 
            +
                measure->multiplier = multiplier_wall_time();
         | 
| 55 | 
            +
                measure->track_allocations = track_allocations;
         | 
| 56 | 
            +
                return measure;
         | 
| 55 57 | 
             
            }
         | 
| 56 58 |  | 
| 57 59 | 
             
            void rp_init_measure_wall_time()
         | 
| @@ -40,7 +40,7 @@ double prof_measure(prof_measurer_t* measurer, rb_trace_arg_t* trace_arg) | |
| 40 40 | 
             
            }
         | 
| 41 41 |  | 
| 42 42 | 
             
            /* =======  prof_measurement_t   ========*/
         | 
| 43 | 
            -
            prof_measurement_t  | 
| 43 | 
            +
            prof_measurement_t* prof_measurement_create(void)
         | 
| 44 44 | 
             
            {
         | 
| 45 45 | 
             
                prof_measurement_t* result = ALLOC(prof_measurement_t);
         | 
| 46 46 | 
             
                result->total_time = 0;
         | 
| @@ -51,67 +51,78 @@ prof_measurement_t *prof_measurement_create(void) | |
| 51 51 | 
             
                return result;
         | 
| 52 52 | 
             
            }
         | 
| 53 53 |  | 
| 54 | 
            -
             | 
| 55 | 
            -
            prof_measurement_ruby_gc_free(void *data)
         | 
| 54 | 
            +
            void prof_measurement_mark(void* data)
         | 
| 56 55 | 
             
            {
         | 
| 57 | 
            -
                 | 
| 56 | 
            +
                if (!data) return;
         | 
| 58 57 |  | 
| 58 | 
            +
                prof_measurement_t* measurement_data = (prof_measurement_t*)data;
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                if (measurement_data->object != Qnil)
         | 
| 61 | 
            +
                    rb_gc_mark(measurement_data->object);
         | 
| 62 | 
            +
            }
         | 
| 63 | 
            +
             | 
| 64 | 
            +
            static void prof_measurement_ruby_gc_free(void* data)
         | 
| 65 | 
            +
            {
         | 
| 66 | 
            +
                if (data)
         | 
| 67 | 
            +
                {
         | 
| 68 | 
            +
                    // Measurements are freed by their owning object (call info or method)
         | 
| 69 | 
            +
                    prof_measurement_t* measurement = (prof_measurement_t*)data;
         | 
| 70 | 
            +
                    measurement->object = Qnil;
         | 
| 71 | 
            +
                }
         | 
| 72 | 
            +
            }
         | 
| 73 | 
            +
             | 
| 74 | 
            +
            void prof_measurement_free(prof_measurement_t* measurement)
         | 
| 75 | 
            +
            {
         | 
| 59 76 | 
             
                /* Has this measurement object been accessed by Ruby?  If
         | 
| 60 77 | 
             
                   yes clean it up so to avoid a segmentation fault. */
         | 
| 61 78 | 
             
                if (measurement->object != Qnil)
         | 
| 62 79 | 
             
                {
         | 
| 63 | 
            -
                     | 
| 64 | 
            -
                    RDATA(measurement->object)->dfree = NULL;
         | 
| 65 | 
            -
                    RDATA(measurement->object)->data = NULL;
         | 
| 80 | 
            +
                    RTYPEDDATA(measurement->object)->data = NULL;
         | 
| 66 81 | 
             
                    measurement->object = Qnil;
         | 
| 67 82 | 
             
                }
         | 
| 68 | 
            -
            }
         | 
| 69 83 |  | 
| 70 | 
            -
            void
         | 
| 71 | 
            -
            prof_measurement_free(prof_measurement_t* measurement)
         | 
| 72 | 
            -
            {
         | 
| 73 | 
            -
                prof_measurement_ruby_gc_free(measurement);
         | 
| 74 84 | 
             
                xfree(measurement);
         | 
| 75 85 | 
             
            }
         | 
| 76 86 |  | 
| 77 | 
            -
            size_t
         | 
| 78 | 
            -
            prof_measurement_size(const void *data)
         | 
| 87 | 
            +
            size_t prof_measurement_size(const void* data)
         | 
| 79 88 | 
             
            {
         | 
| 80 89 | 
             
                return sizeof(prof_measurement_t);
         | 
| 81 90 | 
             
            }
         | 
| 82 91 |  | 
| 83 | 
            -
             | 
| 84 | 
            -
            prof_measurement_mark(void *data)
         | 
| 92 | 
            +
            static const rb_data_type_t measurement_type =
         | 
| 85 93 | 
             
            {
         | 
| 86 | 
            -
                 | 
| 87 | 
            -
                 | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 94 | 
            +
                .wrap_struct_name = "Measurement",
         | 
| 95 | 
            +
                .function =
         | 
| 96 | 
            +
                {
         | 
| 97 | 
            +
                    .dmark = prof_measurement_mark,
         | 
| 98 | 
            +
                    .dfree = prof_measurement_ruby_gc_free,
         | 
| 99 | 
            +
                    .dsize = prof_measurement_size,
         | 
| 100 | 
            +
                },
         | 
| 101 | 
            +
                .data = NULL,
         | 
| 102 | 
            +
                .flags = RUBY_TYPED_FREE_IMMEDIATELY
         | 
| 103 | 
            +
            }; 
         | 
| 90 104 |  | 
| 91 | 
            -
            VALUE
         | 
| 92 | 
            -
            prof_measurement_wrap(prof_measurement_t* measurement)
         | 
| 105 | 
            +
            VALUE prof_measurement_wrap(prof_measurement_t* measurement)
         | 
| 93 106 | 
             
            {
         | 
| 94 107 | 
             
                if (measurement->object == Qnil)
         | 
| 95 108 | 
             
                {
         | 
| 96 | 
            -
                    measurement->object =  | 
| 109 | 
            +
                    measurement->object = TypedData_Wrap_Struct(cRpMeasurement, &measurement_type, measurement);
         | 
| 97 110 | 
             
                }
         | 
| 98 111 | 
             
                return measurement->object;
         | 
| 99 112 | 
             
            }
         | 
| 100 113 |  | 
| 101 | 
            -
            static VALUE
         | 
| 102 | 
            -
            prof_measurement_allocate(VALUE klass)
         | 
| 114 | 
            +
            static VALUE prof_measurement_allocate(VALUE klass)
         | 
| 103 115 | 
             
            {
         | 
| 104 | 
            -
                prof_measurement_t  | 
| 116 | 
            +
                prof_measurement_t* measurement = prof_measurement_create();
         | 
| 105 117 | 
             
                measurement->object = prof_measurement_wrap(measurement);
         | 
| 106 118 | 
             
                return measurement->object;
         | 
| 107 119 | 
             
            }
         | 
| 108 120 |  | 
| 109 | 
            -
            prof_measurement_t*
         | 
| 110 | 
            -
            prof_get_measurement(VALUE self)
         | 
| 121 | 
            +
            prof_measurement_t* prof_get_measurement(VALUE self)
         | 
| 111 122 | 
             
            {
         | 
| 112 123 | 
             
                /* Can't use Data_Get_Struct because that triggers the event hook
         | 
| 113 124 | 
             
                   ending up in endless recursion. */
         | 
| 114 | 
            -
                prof_measurement_t* result =  | 
| 125 | 
            +
                prof_measurement_t* result = RTYPEDDATA_DATA(self);
         | 
| 115 126 |  | 
| 116 127 | 
             
                if (!result)
         | 
| 117 128 | 
             
                    rb_raise(rb_eRuntimeError, "This RubyProf::Measurement instance has already been freed, likely because its profile has been freed.");
         | 
| @@ -123,8 +134,7 @@ prof_get_measurement(VALUE self) | |
| 123 134 | 
             
               total_time -> float
         | 
| 124 135 |  | 
| 125 136 | 
             
            Returns the total amount of time spent in this method and its children. */
         | 
| 126 | 
            -
            static VALUE
         | 
| 127 | 
            -
            prof_measurement_total_time(VALUE self)
         | 
| 137 | 
            +
            static VALUE prof_measurement_total_time(VALUE self)
         | 
| 128 138 | 
             
            {
         | 
| 129 139 | 
             
                prof_measurement_t* result = prof_get_measurement(self);
         | 
| 130 140 | 
             
                return rb_float_new(result->total_time);
         | 
| @@ -146,8 +156,7 @@ prof_measurement_self_time(VALUE self) | |
| 146 156 | 
             
               wait_time -> float
         | 
| 147 157 |  | 
| 148 158 | 
             
            Returns the total amount of time this method waited for other threads. */
         | 
| 149 | 
            -
            static VALUE
         | 
| 150 | 
            -
            prof_measurement_wait_time(VALUE self)
         | 
| 159 | 
            +
            static VALUE prof_measurement_wait_time(VALUE self)
         | 
| 151 160 | 
             
            {
         | 
| 152 161 | 
             
                prof_measurement_t* result = prof_get_measurement(self);
         | 
| 153 162 |  | 
| @@ -158,10 +167,9 @@ prof_measurement_wait_time(VALUE self) | |
| 158 167 | 
             
               called -> int
         | 
| 159 168 |  | 
| 160 169 | 
             
            Returns the total amount of times this method was called. */
         | 
| 161 | 
            -
            static VALUE
         | 
| 162 | 
            -
            prof_measurement_called(VALUE self)
         | 
| 170 | 
            +
            static VALUE prof_measurement_called(VALUE self)
         | 
| 163 171 | 
             
            {
         | 
| 164 | 
            -
                prof_measurement_t  | 
| 172 | 
            +
                prof_measurement_t* result = prof_get_measurement(self);
         | 
| 165 173 | 
             
                return INT2NUM(result->called);
         | 
| 166 174 | 
             
            }
         | 
| 167 175 |  | 
| @@ -169,10 +177,9 @@ prof_measurement_called(VALUE self) | |
| 169 177 | 
             
               called=n -> n
         | 
| 170 178 |  | 
| 171 179 | 
             
            Sets the call count to n. */
         | 
| 172 | 
            -
            static VALUE
         | 
| 173 | 
            -
            prof_measurement_set_called(VALUE self, VALUE called)
         | 
| 180 | 
            +
            static VALUE prof_measurement_set_called(VALUE self, VALUE called)
         | 
| 174 181 | 
             
            {
         | 
| 175 | 
            -
                prof_measurement_t  | 
| 182 | 
            +
                prof_measurement_t* result = prof_get_measurement(self);
         | 
| 176 183 | 
             
                result->called = NUM2INT(called);
         | 
| 177 184 | 
             
                return called;
         | 
| 178 185 | 
             
            }
         | 
| @@ -215,7 +222,7 @@ void rp_init_measure() | |
| 215 222 | 
             
                rp_init_measure_allocations();
         | 
| 216 223 | 
             
                rp_init_measure_memory();
         | 
| 217 224 |  | 
| 218 | 
            -
                cRpMeasurement = rb_define_class_under(mProf, "Measurement",  | 
| 225 | 
            +
                cRpMeasurement = rb_define_class_under(mProf, "Measurement", rb_cObject);
         | 
| 219 226 | 
             
                rb_undef_method(CLASS_OF(cRpMeasurement), "new");
         | 
| 220 227 | 
             
                rb_define_alloc_func(cRpMeasurement, prof_measurement_allocate);
         | 
| 221 228 |  | 
| @@ -8,7 +8,7 @@ | |
| 8 8 |  | 
| 9 9 | 
             
            extern VALUE mMeasure;
         | 
| 10 10 |  | 
| 11 | 
            -
            typedef double (*get_measurement)(rb_trace_arg_t  | 
| 11 | 
            +
            typedef double (*get_measurement)(rb_trace_arg_t* trace_arg);
         | 
| 12 12 |  | 
| 13 13 | 
             
            typedef enum
         | 
| 14 14 | 
             
            {
         | 
| @@ -18,7 +18,7 @@ typedef enum | |
| 18 18 | 
             
                MEASURE_MEMORY
         | 
| 19 19 | 
             
            } prof_measure_mode_t;
         | 
| 20 20 |  | 
| 21 | 
            -
            typedef struct
         | 
| 21 | 
            +
            typedef struct prof_measurer_t
         | 
| 22 22 | 
             
            {
         | 
| 23 23 | 
             
                get_measurement measure;
         | 
| 24 24 | 
             
                prof_measure_mode_t mode;
         | 
| @@ -36,14 +36,14 @@ typedef struct prof_measurement_t | |
| 36 36 | 
             
                VALUE object;
         | 
| 37 37 | 
             
            } prof_measurement_t;
         | 
| 38 38 |  | 
| 39 | 
            -
            prof_measurer_t  | 
| 40 | 
            -
            double prof_measure(prof_measurer_t  | 
| 39 | 
            +
            prof_measurer_t* prof_get_measurer(prof_measure_mode_t measure, bool track_allocations);
         | 
| 40 | 
            +
            double prof_measure(prof_measurer_t* measurer, rb_trace_arg_t* trace_arg);
         | 
| 41 41 |  | 
| 42 | 
            -
            prof_measurement_t  | 
| 42 | 
            +
            prof_measurement_t* prof_measurement_create(void);
         | 
| 43 43 | 
             
            void prof_measurement_free(prof_measurement_t* measurement);
         | 
| 44 | 
            -
            VALUE prof_measurement_wrap(prof_measurement_t  | 
| 44 | 
            +
            VALUE prof_measurement_wrap(prof_measurement_t* measurement);
         | 
| 45 45 | 
             
            prof_measurement_t* prof_get_measurement(VALUE self);
         | 
| 46 | 
            -
            void prof_measurement_mark(void  | 
| 46 | 
            +
            void prof_measurement_mark(void* data);
         | 
| 47 47 |  | 
| 48 48 | 
             
            void rp_init_measure(void);
         | 
| 49 49 |  | 
    
        data/ext/ruby_prof/rp_method.c
    CHANGED
    
    | @@ -2,14 +2,13 @@ | |
| 2 2 | 
             
               Please see the LICENSE file for copyright and distribution information */
         | 
| 3 3 |  | 
| 4 4 | 
             
            #include "rp_allocation.h"
         | 
| 5 | 
            -
            #include " | 
| 5 | 
            +
            #include "rp_call_trees.h"
         | 
| 6 6 | 
             
            #include "rp_method.h"
         | 
| 7 7 |  | 
| 8 8 | 
             
            VALUE cRpMethodInfo;
         | 
| 9 9 |  | 
| 10 10 | 
             
            /* ================  Helper Functions  =================*/
         | 
| 11 | 
            -
            VALUE
         | 
| 12 | 
            -
            resolve_klass(VALUE klass, unsigned int *klass_flags)
         | 
| 11 | 
            +
            VALUE resolve_klass(VALUE klass, unsigned int* klass_flags)
         | 
| 13 12 | 
             
            {
         | 
| 14 13 | 
             
                VALUE result = klass;
         | 
| 15 14 |  | 
| @@ -62,8 +61,7 @@ resolve_klass(VALUE klass, unsigned int *klass_flags) | |
| 62 61 | 
             
                return result;
         | 
| 63 62 | 
             
            }
         | 
| 64 63 |  | 
| 65 | 
            -
            VALUE
         | 
| 66 | 
            -
            resolve_klass_name(VALUE klass, unsigned int* klass_flags)
         | 
| 64 | 
            +
            VALUE resolve_klass_name(VALUE klass, unsigned int* klass_flags)
         | 
| 67 65 | 
             
            {
         | 
| 68 66 | 
             
                VALUE result = Qnil;
         | 
| 69 67 |  | 
| @@ -83,8 +81,7 @@ resolve_klass_name(VALUE klass, unsigned int* klass_flags) | |
| 83 81 | 
             
                return result;
         | 
| 84 82 | 
             
            }
         | 
| 85 83 |  | 
| 86 | 
            -
            st_data_t
         | 
| 87 | 
            -
            method_key(VALUE klass, VALUE msym)
         | 
| 84 | 
            +
            st_data_t method_key(VALUE klass, VALUE msym)
         | 
| 88 85 | 
             
            {
         | 
| 89 86 | 
             
                VALUE resolved_klass = klass;
         | 
| 90 87 |  | 
| @@ -104,21 +101,18 @@ method_key(VALUE klass, VALUE msym) | |
| 104 101 | 
             
            }
         | 
| 105 102 |  | 
| 106 103 | 
             
            /* ======   Allocation Table  ====== */
         | 
| 107 | 
            -
            st_table*
         | 
| 108 | 
            -
            allocations_table_create()
         | 
| 104 | 
            +
            st_table* allocations_table_create()
         | 
| 109 105 | 
             
            {
         | 
| 110 | 
            -
                return  | 
| 106 | 
            +
                return rb_st_init_numtable();
         | 
| 111 107 | 
             
            }
         | 
| 112 108 |  | 
| 113 | 
            -
            static int
         | 
| 114 | 
            -
             | 
| 115 | 
            -
            { 
         | 
| 109 | 
            +
            static int allocations_table_free_iterator(st_data_t key, st_data_t value, st_data_t dummy)
         | 
| 110 | 
            +
            {
         | 
| 116 111 | 
             
                prof_allocation_free((prof_allocation_t*)value);
         | 
| 117 112 | 
             
                return ST_CONTINUE;
         | 
| 118 113 | 
             
            }
         | 
| 119 114 |  | 
| 120 | 
            -
            static int
         | 
| 121 | 
            -
            prof_method_collect_allocations(st_data_t key, st_data_t value, st_data_t result)
         | 
| 115 | 
            +
            static int prof_method_collect_allocations(st_data_t key, st_data_t value, st_data_t result)
         | 
| 122 116 | 
             
            {
         | 
| 123 117 | 
             
                prof_allocation_t* allocation = (prof_allocation_t*)value;
         | 
| 124 118 | 
             
                VALUE arr = (VALUE)result;
         | 
| @@ -126,28 +120,25 @@ prof_method_collect_allocations(st_data_t key, st_data_t value, st_data_t result | |
| 126 120 | 
             
                return ST_CONTINUE;
         | 
| 127 121 | 
             
            }
         | 
| 128 122 |  | 
| 129 | 
            -
            static int
         | 
| 130 | 
            -
            prof_method_mark_allocations(st_data_t key, st_data_t value, st_data_t data)
         | 
| 123 | 
            +
            static int prof_method_mark_allocations(st_data_t key, st_data_t value, st_data_t data)
         | 
| 131 124 | 
             
            {
         | 
| 132 125 | 
             
                prof_allocation_t* allocation = (prof_allocation_t*)value;
         | 
| 133 126 | 
             
                prof_allocation_mark(allocation);
         | 
| 134 127 | 
             
                return ST_CONTINUE;
         | 
| 135 128 | 
             
            }
         | 
| 136 129 |  | 
| 137 | 
            -
            void
         | 
| 138 | 
            -
            allocations_table_free(st_table* table)
         | 
| 130 | 
            +
            void allocations_table_free(st_table* table)
         | 
| 139 131 | 
             
            {
         | 
| 140 | 
            -
                 | 
| 141 | 
            -
                 | 
| 132 | 
            +
                rb_st_foreach(table, allocations_table_free_iterator, 0);
         | 
| 133 | 
            +
                rb_st_free_table(table);
         | 
| 142 134 | 
             
            }
         | 
| 143 135 |  | 
| 144 136 | 
             
            /* ================  prof_method_t   =================*/
         | 
| 145 | 
            -
             | 
| 146 | 
            -
            prof_get_method(VALUE self)
         | 
| 137 | 
            +
            prof_method_t* prof_get_method(VALUE self)
         | 
| 147 138 | 
             
            {
         | 
| 148 139 | 
             
                /* Can't use Data_Get_Struct because that triggers the event hook
         | 
| 149 140 | 
             
                   ending up in endless recursion. */
         | 
| 150 | 
            -
                prof_method_t* result =  | 
| 141 | 
            +
                prof_method_t* result = RTYPEDDATA_DATA(self);
         | 
| 151 142 |  | 
| 152 143 | 
             
                if (!result)
         | 
| 153 144 | 
             
                    rb_raise(rb_eRuntimeError, "This RubyProf::MethodInfo instance has already been freed, likely because its profile has been freed.");
         | 
| @@ -155,27 +146,24 @@ prof_get_method(VALUE self) | |
| 155 146 | 
             
                return result;
         | 
| 156 147 | 
             
            }
         | 
| 157 148 |  | 
| 158 | 
            -
            prof_method_t*
         | 
| 159 | 
            -
            prof_method_create(VALUE klass, VALUE msym, VALUE source_file, int source_line)
         | 
| 149 | 
            +
            prof_method_t* prof_method_create(VALUE profile, VALUE klass, VALUE msym, VALUE source_file, int source_line)
         | 
| 160 150 | 
             
            {
         | 
| 161 | 
            -
                prof_method_t  | 
| 151 | 
            +
                prof_method_t* result = ALLOC(prof_method_t);
         | 
| 152 | 
            +
                result->profile = profile;
         | 
| 153 | 
            +
             | 
| 162 154 | 
             
                result->key = method_key(klass, msym);
         | 
| 163 155 | 
             
                result->klass_flags = 0;
         | 
| 164 156 |  | 
| 165 | 
            -
                /* Note we do not call resolve_klass_name now because that causes an object allocation that shows up | 
| 157 | 
            +
                /* Note we do not call resolve_klass_name now because that causes an object allocation that shows up
         | 
| 166 158 | 
             
                   in the allocation results so we want to avoid it until after the profile run is complete. */
         | 
| 167 159 | 
             
                result->klass = resolve_klass(klass, &result->klass_flags);
         | 
| 168 160 | 
             
                result->klass_name = Qnil;
         | 
| 169 161 | 
             
                result->method_name = msym;
         | 
| 170 162 | 
             
                result->measurement = prof_measurement_create();
         | 
| 171 163 |  | 
| 172 | 
            -
                result-> | 
| 173 | 
            -
                result->excluded = false;
         | 
| 174 | 
            -
             | 
| 175 | 
            -
                result->parent_call_infos = method_table_create();
         | 
| 176 | 
            -
                result->child_call_infos = method_table_create();
         | 
| 164 | 
            +
                result->call_trees = prof_call_trees_create();
         | 
| 177 165 | 
             
                result->allocations_table = allocations_table_create();
         | 
| 178 | 
            -
             | 
| 166 | 
            +
             | 
| 179 167 | 
             
                result->visits = 0;
         | 
| 180 168 | 
             
                result->recursive = false;
         | 
| 181 169 |  | 
| @@ -187,180 +175,127 @@ prof_method_create(VALUE klass, VALUE msym, VALUE source_file, int source_line) | |
| 187 175 | 
             
                return result;
         | 
| 188 176 | 
             
            }
         | 
| 189 177 |  | 
| 190 | 
            -
            prof_method_t*
         | 
| 191 | 
            -
            prof_method_create_excluded(VALUE klass, VALUE msym)
         | 
| 192 | 
            -
            {
         | 
| 193 | 
            -
                prof_method_t* result = prof_method_create(klass, msym, Qnil, 0);
         | 
| 194 | 
            -
                result->excluded = 1;
         | 
| 195 | 
            -
                return result;
         | 
| 196 | 
            -
            }
         | 
| 197 | 
            -
             | 
| 198 | 
            -
            static int
         | 
| 199 | 
            -
            prof_method_collect_call_infos(st_data_t key, st_data_t value, st_data_t result)
         | 
| 200 | 
            -
            {
         | 
| 201 | 
            -
                prof_call_info_t* call_info = (prof_call_info_t*)value;
         | 
| 202 | 
            -
                VALUE arr = (VALUE)result;
         | 
| 203 | 
            -
                rb_ary_push(arr, prof_call_info_wrap(call_info));
         | 
| 204 | 
            -
                return ST_CONTINUE;
         | 
| 205 | 
            -
            }
         | 
| 206 | 
            -
             | 
| 207 | 
            -
            static int
         | 
| 208 | 
            -
            prof_method_mark_call_infos(st_data_t key, st_data_t value, st_data_t data)
         | 
| 209 | 
            -
            {
         | 
| 210 | 
            -
                prof_call_info_t* call_info = (prof_call_info_t*)value;
         | 
| 211 | 
            -
                prof_call_info_mark(call_info);
         | 
| 212 | 
            -
                return ST_CONTINUE;
         | 
| 213 | 
            -
            }
         | 
| 214 | 
            -
             | 
| 215 | 
            -
            static int
         | 
| 216 | 
            -
            call_infos_free_iterator(st_data_t key, st_data_t value, st_data_t dummy)
         | 
| 217 | 
            -
            {
         | 
| 218 | 
            -
                prof_call_info_free((prof_call_info_t*)value);
         | 
| 219 | 
            -
                return ST_CONTINUE;
         | 
| 220 | 
            -
            }
         | 
| 221 | 
            -
             | 
| 222 | 
            -
            void
         | 
| 223 | 
            -
            call_info_table_free(st_table* table)
         | 
| 224 | 
            -
            {
         | 
| 225 | 
            -
                st_foreach(table, call_infos_free_iterator, 0);
         | 
| 226 | 
            -
                st_free_table(table);
         | 
| 227 | 
            -
            }
         | 
| 228 | 
            -
             | 
| 229 178 | 
             
            /* The underlying c structures are freed when the parent profile is freed.
         | 
| 230 179 | 
             
               However, on shutdown the Ruby GC frees objects in any will-nilly order.
         | 
| 231 180 | 
             
               That means the ruby thread object wrapping the c thread struct may
         | 
| 232 181 | 
             
               be freed before the parent profile.  Thus we add in a free function
         | 
| 233 182 | 
             
               for the garbage collector so that if it does get called will nil
         | 
| 234 183 | 
             
               out our Ruby object reference.*/
         | 
| 235 | 
            -
            static void
         | 
| 236 | 
            -
            prof_method_ruby_gc_free(void *data)
         | 
| 184 | 
            +
            static void prof_method_ruby_gc_free(void* data)
         | 
| 237 185 | 
             
            {
         | 
| 238 | 
            -
                 | 
| 239 | 
            -
             | 
| 240 | 
            -
             | 
| 241 | 
            -
            	   yes clean it up so to avoid a segmentation fault. */
         | 
| 242 | 
            -
            	if (method->object != Qnil)
         | 
| 243 | 
            -
            	{
         | 
| 244 | 
            -
                    RDATA(method->object)->dmark = NULL;
         | 
| 245 | 
            -
                    RDATA(method->object)->dfree = NULL;
         | 
| 246 | 
            -
                    RDATA(method->object)->data = NULL;
         | 
| 186 | 
            +
                if (data)
         | 
| 187 | 
            +
                {
         | 
| 188 | 
            +
                    prof_method_t* method = (prof_method_t*)data;
         | 
| 247 189 | 
             
                    method->object = Qnil;
         | 
| 248 190 | 
             
                }
         | 
| 249 | 
            -
                method->klass_name = Qnil;
         | 
| 250 | 
            -
                method->method_name = Qnil;
         | 
| 251 191 | 
             
            }
         | 
| 252 192 |  | 
| 253 | 
            -
            static void
         | 
| 254 | 
            -
            prof_method_free(prof_method_t* method)
         | 
| 193 | 
            +
            static void prof_method_free(prof_method_t* method)
         | 
| 255 194 | 
             
            {
         | 
| 256 | 
            -
             | 
| 257 | 
            -
             | 
| 258 | 
            -
             | 
| 259 | 
            -
                 | 
| 260 | 
            -
             | 
| 261 | 
            -
             | 
| 262 | 
            -
                 | 
| 195 | 
            +
                /* Has this method object been accessed by Ruby?  If
         | 
| 196 | 
            +
                   yes clean it up so to avoid a segmentation fault. */
         | 
| 197 | 
            +
                if (method->object != Qnil)
         | 
| 198 | 
            +
                {
         | 
| 199 | 
            +
                    RTYPEDDATA(method->object)->data = NULL;
         | 
| 200 | 
            +
                    method->object = Qnil;
         | 
| 201 | 
            +
                }
         | 
| 263 202 |  | 
| 203 | 
            +
                allocations_table_free(method->allocations_table);
         | 
| 204 | 
            +
                prof_call_trees_free(method->call_trees);
         | 
| 264 205 | 
             
                prof_measurement_free(method->measurement);
         | 
| 265 206 | 
             
                xfree(method);
         | 
| 266 207 | 
             
            }
         | 
| 267 208 |  | 
| 268 | 
            -
            size_t
         | 
| 269 | 
            -
            prof_method_size(const void *data)
         | 
| 209 | 
            +
            size_t prof_method_size(const void* data)
         | 
| 270 210 | 
             
            {
         | 
| 271 211 | 
             
                return sizeof(prof_method_t);
         | 
| 272 212 | 
             
            }
         | 
| 273 213 |  | 
| 274 | 
            -
            void
         | 
| 275 | 
            -
            prof_method_mark(void *data)
         | 
| 214 | 
            +
            void prof_method_mark(void* data)
         | 
| 276 215 | 
             
            {
         | 
| 216 | 
            +
                if (!data) return;
         | 
| 217 | 
            +
             | 
| 277 218 | 
             
                prof_method_t* method = (prof_method_t*)data;
         | 
| 219 | 
            +
             | 
| 220 | 
            +
                if (method->profile != Qnil)
         | 
| 221 | 
            +
                    rb_gc_mark(method->profile);
         | 
| 222 | 
            +
             | 
| 223 | 
            +
                if (method->object != Qnil)
         | 
| 224 | 
            +
                    rb_gc_mark(method->object);
         | 
| 225 | 
            +
             | 
| 278 226 | 
             
                rb_gc_mark(method->klass_name);
         | 
| 279 227 | 
             
                rb_gc_mark(method->method_name);
         | 
| 280 | 
            -
                
         | 
| 228 | 
            +
                rb_gc_mark(method->source_file);
         | 
| 229 | 
            +
             | 
| 281 230 | 
             
                if (method->klass != Qnil)
         | 
| 282 231 | 
             
                    rb_gc_mark(method->klass);
         | 
| 283 232 |  | 
| 284 | 
            -
                if (method->object != Qnil)
         | 
| 285 | 
            -
            		rb_gc_mark(method->object);
         | 
| 286 | 
            -
             | 
| 287 233 | 
             
                prof_measurement_mark(method->measurement);
         | 
| 288 | 
            -
             | 
| 289 | 
            -
                 | 
| 290 | 
            -
                st_foreach(method->child_call_infos, prof_method_mark_call_infos, 0);
         | 
| 291 | 
            -
                st_foreach(method->allocations_table, prof_method_mark_allocations, 0);
         | 
| 234 | 
            +
             | 
| 235 | 
            +
                rb_st_foreach(method->allocations_table, prof_method_mark_allocations, 0);
         | 
| 292 236 | 
             
            }
         | 
| 293 237 |  | 
| 294 | 
            -
            static VALUE
         | 
| 295 | 
            -
            prof_method_allocate(VALUE klass)
         | 
| 238 | 
            +
            static VALUE prof_method_allocate(VALUE klass)
         | 
| 296 239 | 
             
            {
         | 
| 297 | 
            -
                prof_method_t* method_data = prof_method_create(Qnil, Qnil, Qnil, 0);
         | 
| 240 | 
            +
                prof_method_t* method_data = prof_method_create(Qnil, Qnil, Qnil, Qnil, 0);
         | 
| 298 241 | 
             
                method_data->object = prof_method_wrap(method_data);
         | 
| 299 242 | 
             
                return method_data->object;
         | 
| 300 243 | 
             
            }
         | 
| 301 244 |  | 
| 302 | 
            -
             | 
| 303 | 
            -
            prof_method_wrap(prof_method_t *method)
         | 
| 245 | 
            +
            static const rb_data_type_t method_info_type =
         | 
| 304 246 | 
             
            {
         | 
| 305 | 
            -
             | 
| 306 | 
            -
             | 
| 307 | 
            -
             | 
| 308 | 
            -
             | 
| 309 | 
            -
             | 
| 310 | 
            -
             | 
| 247 | 
            +
                .wrap_struct_name = "MethodInfo",
         | 
| 248 | 
            +
                .function =
         | 
| 249 | 
            +
                {
         | 
| 250 | 
            +
                    .dmark = prof_method_mark,
         | 
| 251 | 
            +
                    .dfree = prof_method_ruby_gc_free,
         | 
| 252 | 
            +
                    .dsize = prof_method_size,
         | 
| 253 | 
            +
                },
         | 
| 254 | 
            +
                .data = NULL,
         | 
| 255 | 
            +
                .flags = RUBY_TYPED_FREE_IMMEDIATELY
         | 
| 256 | 
            +
            }; 
         | 
| 311 257 |  | 
| 312 | 
            -
            prof_method_t  | 
| 313 | 
            -
            prof_method_get(VALUE self)
         | 
| 258 | 
            +
            VALUE prof_method_wrap(prof_method_t* method)
         | 
| 314 259 | 
             
            {
         | 
| 315 | 
            -
                 | 
| 316 | 
            -
                   ending up in endless recursion. */
         | 
| 317 | 
            -
            	prof_method_t* result = DATA_PTR(self);
         | 
| 318 | 
            -
             | 
| 319 | 
            -
            	if (!result)
         | 
| 260 | 
            +
                if (method->object == Qnil)
         | 
| 320 261 | 
             
                {
         | 
| 321 | 
            -
             | 
| 322 | 
            -
             | 
| 323 | 
            -
             | 
| 324 | 
            -
               return result;
         | 
| 262 | 
            +
                    method->object = TypedData_Wrap_Struct(cRpMethodInfo, &method_info_type, method);
         | 
| 263 | 
            +
                }
         | 
| 264 | 
            +
                return method->object;
         | 
| 325 265 | 
             
            }
         | 
| 326 266 |  | 
| 327 | 
            -
            st_table  | 
| 328 | 
            -
            method_table_create()
         | 
| 267 | 
            +
            st_table* method_table_create()
         | 
| 329 268 | 
             
            {
         | 
| 330 | 
            -
                return  | 
| 269 | 
            +
                return rb_st_init_numtable();
         | 
| 331 270 | 
             
            }
         | 
| 332 271 |  | 
| 333 | 
            -
            static int
         | 
| 334 | 
            -
            method_table_free_iterator(st_data_t key, st_data_t value, st_data_t dummy)
         | 
| 272 | 
            +
            static int method_table_free_iterator(st_data_t key, st_data_t value, st_data_t dummy)
         | 
| 335 273 | 
             
            {
         | 
| 336 | 
            -
                prof_method_free((prof_method_t | 
| 274 | 
            +
                prof_method_free((prof_method_t*)value);
         | 
| 337 275 | 
             
                return ST_CONTINUE;
         | 
| 338 276 | 
             
            }
         | 
| 339 277 |  | 
| 340 | 
            -
            void
         | 
| 341 | 
            -
            method_table_free(st_table *table)
         | 
| 278 | 
            +
            void method_table_free(st_table* table)
         | 
| 342 279 | 
             
            {
         | 
| 343 | 
            -
                 | 
| 344 | 
            -
                 | 
| 280 | 
            +
                rb_st_foreach(table, method_table_free_iterator, 0);
         | 
| 281 | 
            +
                rb_st_free_table(table);
         | 
| 345 282 | 
             
            }
         | 
| 346 283 |  | 
| 347 | 
            -
            size_t
         | 
| 348 | 
            -
            method_table_insert(st_table *table, st_data_t key, prof_method_t *val)
         | 
| 284 | 
            +
            size_t method_table_insert(st_table* table, st_data_t key, prof_method_t* val)
         | 
| 349 285 | 
             
            {
         | 
| 350 | 
            -
                return  | 
| 286 | 
            +
                return rb_st_insert(table, (st_data_t)key, (st_data_t)val);
         | 
| 351 287 | 
             
            }
         | 
| 352 288 |  | 
| 353 | 
            -
            prof_method_t *
         | 
| 354 | 
            -
            method_table_lookup(st_table *table, st_data_t key)
         | 
| 289 | 
            +
            prof_method_t* method_table_lookup(st_table* table, st_data_t key)
         | 
| 355 290 | 
             
            {
         | 
| 356 291 | 
             
                st_data_t val;
         | 
| 357 | 
            -
                if ( | 
| 292 | 
            +
                if (rb_st_lookup(table, (st_data_t)key, &val))
         | 
| 358 293 | 
             
                {
         | 
| 359 | 
            -
             | 
| 294 | 
            +
                    return (prof_method_t*)val;
         | 
| 360 295 | 
             
                }
         | 
| 361 296 | 
             
                else
         | 
| 362 297 | 
             
                {
         | 
| 363 | 
            -
             | 
| 298 | 
            +
                    return NULL;
         | 
| 364 299 | 
             
                }
         | 
| 365 300 | 
             
            }
         | 
| 366 301 |  | 
| @@ -374,42 +309,15 @@ created.  RubyProf::MethodInfo objects can be accessed via | |
| 374 309 | 
             
            the RubyProf::Profile object.
         | 
| 375 310 | 
             
            */
         | 
| 376 311 |  | 
| 377 | 
            -
            /* call-seq:
         | 
| 378 | 
            -
               callers -> array
         | 
| 379 | 
            -
             | 
| 380 | 
            -
            Returns an array of call info objects that called this method  (ie, parents).*/
         | 
| 381 | 
            -
            static VALUE
         | 
| 382 | 
            -
            prof_method_callers(VALUE self)
         | 
| 383 | 
            -
            {
         | 
| 384 | 
            -
                prof_method_t* method = prof_get_method(self);
         | 
| 385 | 
            -
                VALUE result = rb_ary_new();
         | 
| 386 | 
            -
                st_foreach(method->parent_call_infos, prof_method_collect_call_infos, result);
         | 
| 387 | 
            -
                return result;
         | 
| 388 | 
            -
            }
         | 
| 389 | 
            -
             | 
| 390 | 
            -
            /* call-seq:
         | 
| 391 | 
            -
               callees -> array
         | 
| 392 | 
            -
             | 
| 393 | 
            -
            Returns an array of call info objects that this method called (ie, children).*/
         | 
| 394 | 
            -
            static VALUE
         | 
| 395 | 
            -
            prof_method_callees(VALUE self)
         | 
| 396 | 
            -
            {
         | 
| 397 | 
            -
                prof_method_t* method = prof_get_method(self);
         | 
| 398 | 
            -
                VALUE result = rb_ary_new();
         | 
| 399 | 
            -
                st_foreach(method->child_call_infos, prof_method_collect_call_infos, result);
         | 
| 400 | 
            -
                return result;
         | 
| 401 | 
            -
            }
         | 
| 402 | 
            -
             | 
| 403 312 | 
             
            /* call-seq:
         | 
| 404 313 | 
             
               allocations -> array
         | 
| 405 314 |  | 
| 406 315 | 
             
            Returns an array of allocation information.*/
         | 
| 407 | 
            -
            static VALUE
         | 
| 408 | 
            -
            prof_method_allocations(VALUE self)
         | 
| 316 | 
            +
            static VALUE prof_method_allocations(VALUE self)
         | 
| 409 317 | 
             
            {
         | 
| 410 318 | 
             
                prof_method_t* method = prof_get_method(self);
         | 
| 411 319 | 
             
                VALUE result = rb_ary_new();
         | 
| 412 | 
            -
                 | 
| 320 | 
            +
                rb_st_foreach(method->allocations_table, prof_method_collect_allocations, result);
         | 
| 413 321 | 
             
                return result;
         | 
| 414 322 | 
             
            }
         | 
| 415 323 |  | 
| @@ -417,8 +325,7 @@ prof_method_allocations(VALUE self) | |
| 417 325 | 
             
               called -> Measurement
         | 
| 418 326 |  | 
| 419 327 | 
             
            Returns the measurement associated with this method. */
         | 
| 420 | 
            -
            static VALUE
         | 
| 421 | 
            -
            prof_method_measurement(VALUE self)
         | 
| 328 | 
            +
            static VALUE prof_method_measurement(VALUE self)
         | 
| 422 329 | 
             
            {
         | 
| 423 330 | 
             
                prof_method_t* method = prof_get_method(self);
         | 
| 424 331 | 
             
                return prof_measurement_wrap(method->measurement);
         | 
| @@ -431,7 +338,7 @@ return the source file of the method | |
| 431 338 | 
             
            */
         | 
| 432 339 | 
             
            static VALUE prof_method_source_file(VALUE self)
         | 
| 433 340 | 
             
            {
         | 
| 434 | 
            -
                prof_method_t* method =  | 
| 341 | 
            +
                prof_method_t* method = prof_get_method(self);
         | 
| 435 342 | 
             
                return method->source_file;
         | 
| 436 343 | 
             
            }
         | 
| 437 344 |  | 
| @@ -439,10 +346,9 @@ static VALUE prof_method_source_file(VALUE self) | |
| 439 346 | 
             
               line_no -> int
         | 
| 440 347 |  | 
| 441 348 | 
             
               returns the line number of the method */
         | 
| 442 | 
            -
            static VALUE
         | 
| 443 | 
            -
            prof_method_line(VALUE self)
         | 
| 349 | 
            +
            static VALUE prof_method_line(VALUE self)
         | 
| 444 350 | 
             
            {
         | 
| 445 | 
            -
                prof_method_t* method =  | 
| 351 | 
            +
                prof_method_t* method = prof_get_method(self);
         | 
| 446 352 | 
             
                return INT2FIX(method->source_line);
         | 
| 447 353 | 
             
            }
         | 
| 448 354 |  | 
| @@ -452,10 +358,9 @@ prof_method_line(VALUE self) | |
| 452 358 | 
             
            Returns the name of this method's class.  Singleton classes
         | 
| 453 359 | 
             
            will have the form <Object::Object>. */
         | 
| 454 360 |  | 
| 455 | 
            -
            static VALUE
         | 
| 456 | 
            -
            prof_method_klass_name(VALUE self)
         | 
| 361 | 
            +
            static VALUE prof_method_klass_name(VALUE self)
         | 
| 457 362 | 
             
            {
         | 
| 458 | 
            -
                prof_method_t  | 
| 363 | 
            +
                prof_method_t* method = prof_get_method(self);
         | 
| 459 364 | 
             
                if (method->klass_name == Qnil)
         | 
| 460 365 | 
             
                    method->klass_name = resolve_klass_name(method->klass, &method->klass_flags);
         | 
| 461 366 |  | 
| @@ -467,10 +372,9 @@ prof_method_klass_name(VALUE self) | |
| 467 372 |  | 
| 468 373 | 
             
            Returns the klass flags */
         | 
| 469 374 |  | 
| 470 | 
            -
            static VALUE
         | 
| 471 | 
            -
            prof_method_klass_flags(VALUE self)
         | 
| 375 | 
            +
            static VALUE prof_method_klass_flags(VALUE self)
         | 
| 472 376 | 
             
            {
         | 
| 473 | 
            -
                prof_method_t* method =  | 
| 377 | 
            +
                prof_method_t* method = prof_get_method(self);
         | 
| 474 378 | 
             
                return INT2FIX(method->klass_flags);
         | 
| 475 379 | 
             
            }
         | 
| 476 380 |  | 
| @@ -480,51 +384,36 @@ prof_method_klass_flags(VALUE self) | |
| 480 384 | 
             
            Returns the name of this method in the format Object#method.  Singletons
         | 
| 481 385 | 
             
            methods will be returned in the format <Object::Object>#method.*/
         | 
| 482 386 |  | 
| 483 | 
            -
            static VALUE
         | 
| 484 | 
            -
            prof_method_name(VALUE self)
         | 
| 387 | 
            +
            static VALUE prof_method_name(VALUE self)
         | 
| 485 388 | 
             
            {
         | 
| 486 | 
            -
                prof_method_t  | 
| 389 | 
            +
                prof_method_t* method = prof_get_method(self);
         | 
| 487 390 | 
             
                return method->method_name;
         | 
| 488 391 | 
             
            }
         | 
| 489 392 |  | 
| 490 | 
            -
            /* call-seq:
         | 
| 491 | 
            -
               root? -> boolean
         | 
| 492 | 
            -
             | 
| 493 | 
            -
               Returns the true if this method is at the top of the call stack */
         | 
| 494 | 
            -
            static VALUE
         | 
| 495 | 
            -
            prof_method_root(VALUE self)
         | 
| 496 | 
            -
            {
         | 
| 497 | 
            -
                prof_method_t *method = prof_method_get(self);
         | 
| 498 | 
            -
                return method->root ? Qtrue : Qfalse;
         | 
| 499 | 
            -
            }
         | 
| 500 | 
            -
             | 
| 501 393 | 
             
            /* call-seq:
         | 
| 502 394 | 
             
               recursive? -> boolean
         | 
| 503 395 |  | 
| 504 396 | 
             
               Returns the true if this method is recursively invoked */
         | 
| 505 | 
            -
            static VALUE
         | 
| 506 | 
            -
            prof_method_recursive(VALUE self)
         | 
| 397 | 
            +
            static VALUE prof_method_recursive(VALUE self)
         | 
| 507 398 | 
             
            {
         | 
| 508 | 
            -
                prof_method_t* method =  | 
| 399 | 
            +
                prof_method_t* method = prof_get_method(self);
         | 
| 509 400 | 
             
                return method->recursive ? Qtrue : Qfalse;
         | 
| 510 401 | 
             
            }
         | 
| 511 402 |  | 
| 512 403 | 
             
            /* call-seq:
         | 
| 513 | 
            -
                | 
| 404 | 
            +
               call_trees -> CallTrees
         | 
| 514 405 |  | 
| 515 | 
            -
             | 
| 516 | 
            -
            static VALUE
         | 
| 517 | 
            -
            prof_method_excluded(VALUE self)
         | 
| 406 | 
            +
            Returns the CallTrees associated with this method. */
         | 
| 407 | 
            +
            static VALUE prof_method_call_trees(VALUE self)
         | 
| 518 408 | 
             
            {
         | 
| 519 | 
            -
                prof_method_t* method =  | 
| 520 | 
            -
                return method-> | 
| 409 | 
            +
                prof_method_t* method = prof_get_method(self);
         | 
| 410 | 
            +
                return prof_call_trees_wrap(method->call_trees);
         | 
| 521 411 | 
             
            }
         | 
| 522 412 |  | 
| 523 413 | 
             
            /* :nodoc: */
         | 
| 524 | 
            -
            static VALUE
         | 
| 525 | 
            -
            prof_method_dump(VALUE self)
         | 
| 414 | 
            +
            static VALUE prof_method_dump(VALUE self)
         | 
| 526 415 | 
             
            {
         | 
| 527 | 
            -
                prof_method_t* method_data =  | 
| 416 | 
            +
                prof_method_t* method_data = prof_get_method(self);
         | 
| 528 417 | 
             
                VALUE result = rb_hash_new();
         | 
| 529 418 |  | 
| 530 419 | 
             
                rb_hash_aset(result, ID2SYM(rb_intern("klass_name")), prof_method_klass_name(self));
         | 
| @@ -532,27 +421,21 @@ prof_method_dump(VALUE self) | |
| 532 421 | 
             
                rb_hash_aset(result, ID2SYM(rb_intern("method_name")), method_data->method_name);
         | 
| 533 422 |  | 
| 534 423 | 
             
                rb_hash_aset(result, ID2SYM(rb_intern("key")), INT2FIX(method_data->key));
         | 
| 535 | 
            -
                rb_hash_aset(result, ID2SYM(rb_intern("root")), prof_method_root(self));
         | 
| 536 424 | 
             
                rb_hash_aset(result, ID2SYM(rb_intern("recursive")), prof_method_recursive(self));
         | 
| 537 | 
            -
                rb_hash_aset(result, ID2SYM(rb_intern("excluded")), prof_method_excluded(self));
         | 
| 538 425 | 
             
                rb_hash_aset(result, ID2SYM(rb_intern("source_file")), method_data->source_file);
         | 
| 539 426 | 
             
                rb_hash_aset(result, ID2SYM(rb_intern("source_line")), INT2FIX(method_data->source_line));
         | 
| 540 427 |  | 
| 428 | 
            +
                rb_hash_aset(result, ID2SYM(rb_intern("call_trees")), prof_call_trees_wrap(method_data->call_trees));
         | 
| 541 429 | 
             
                rb_hash_aset(result, ID2SYM(rb_intern("measurement")), prof_measurement_wrap(method_data->measurement));
         | 
| 542 | 
            -
             | 
| 543 | 
            -
                rb_hash_aset(result, ID2SYM(rb_intern("callers")), prof_method_callers(self));
         | 
| 544 | 
            -
                rb_hash_aset(result, ID2SYM(rb_intern("callees")), prof_method_callees(self));
         | 
| 545 | 
            -
             | 
| 546 430 | 
             
                rb_hash_aset(result, ID2SYM(rb_intern("allocations")), prof_method_allocations(self));
         | 
| 547 431 |  | 
| 548 432 | 
             
                return result;
         | 
| 549 433 | 
             
            }
         | 
| 550 434 |  | 
| 551 435 | 
             
            /* :nodoc: */
         | 
| 552 | 
            -
            static VALUE
         | 
| 553 | 
            -
            prof_method_load(VALUE self, VALUE data)
         | 
| 436 | 
            +
            static VALUE prof_method_load(VALUE self, VALUE data)
         | 
| 554 437 | 
             
            {
         | 
| 555 | 
            -
                prof_method_t* method_data =  | 
| 438 | 
            +
                prof_method_t* method_data = prof_get_method(self);
         | 
| 556 439 | 
             
                method_data->object = self;
         | 
| 557 440 |  | 
| 558 441 | 
             
                method_data->klass_name = rb_hash_aref(data, ID2SYM(rb_intern("klass_name")));
         | 
| @@ -560,42 +443,24 @@ prof_method_load(VALUE self, VALUE data) | |
| 560 443 | 
             
                method_data->method_name = rb_hash_aref(data, ID2SYM(rb_intern("method_name")));
         | 
| 561 444 | 
             
                method_data->key = FIX2LONG(rb_hash_aref(data, ID2SYM(rb_intern("key"))));
         | 
| 562 445 |  | 
| 563 | 
            -
                method_data->root = rb_hash_aref(data, ID2SYM(rb_intern("root"))) == Qtrue ? true : false;
         | 
| 564 446 | 
             
                method_data->recursive = rb_hash_aref(data, ID2SYM(rb_intern("recursive"))) == Qtrue ? true : false;
         | 
| 565 | 
            -
                method_data->excluded = rb_hash_aref(data, ID2SYM(rb_intern("excluded"))) == Qtrue ? true : false;
         | 
| 566 447 |  | 
| 567 448 | 
             
                method_data->source_file = rb_hash_aref(data, ID2SYM(rb_intern("source_file")));
         | 
| 568 449 | 
             
                method_data->source_line = FIX2INT(rb_hash_aref(data, ID2SYM(rb_intern("source_line"))));
         | 
| 569 450 |  | 
| 451 | 
            +
                VALUE call_trees = rb_hash_aref(data, ID2SYM(rb_intern("call_trees")));
         | 
| 452 | 
            +
                method_data->call_trees = prof_get_call_trees(call_trees);
         | 
| 453 | 
            +
             | 
| 570 454 | 
             
                VALUE measurement = rb_hash_aref(data, ID2SYM(rb_intern("measurement")));
         | 
| 571 455 | 
             
                method_data->measurement = prof_get_measurement(measurement);
         | 
| 572 456 |  | 
| 573 | 
            -
                VALUE callers = rb_hash_aref(data, ID2SYM(rb_intern("callers")));
         | 
| 574 | 
            -
                for (int i = 0; i < rb_array_len(callers); i++)
         | 
| 575 | 
            -
                {
         | 
| 576 | 
            -
                    VALUE call_info = rb_ary_entry(callers, i);
         | 
| 577 | 
            -
                    prof_call_info_t *call_info_data = prof_get_call_info(call_info);
         | 
| 578 | 
            -
                    st_data_t key = call_info_data->parent ? call_info_data->parent->key : method_key(Qnil, 0);
         | 
| 579 | 
            -
                    call_info_table_insert(method_data->parent_call_infos, key, call_info_data);
         | 
| 580 | 
            -
                }
         | 
| 581 | 
            -
             | 
| 582 | 
            -
                VALUE callees = rb_hash_aref(data, ID2SYM(rb_intern("callees")));
         | 
| 583 | 
            -
                for (int i = 0; i < rb_array_len(callees); i++)
         | 
| 584 | 
            -
                {
         | 
| 585 | 
            -
                    VALUE call_info = rb_ary_entry(callees, i);
         | 
| 586 | 
            -
                    prof_call_info_t *call_info_data = prof_get_call_info(call_info);
         | 
| 587 | 
            -
             | 
| 588 | 
            -
                    st_data_t key = call_info_data->method ? call_info_data->method->key : method_key(Qnil, 0);
         | 
| 589 | 
            -
                    call_info_table_insert(method_data->child_call_infos, key, call_info_data);
         | 
| 590 | 
            -
                }
         | 
| 591 | 
            -
             | 
| 592 457 | 
             
                VALUE allocations = rb_hash_aref(data, ID2SYM(rb_intern("allocations")));
         | 
| 593 458 | 
             
                for (int i = 0; i < rb_array_len(allocations); i++)
         | 
| 594 459 | 
             
                {
         | 
| 595 460 | 
             
                    VALUE allocation = rb_ary_entry(allocations, i);
         | 
| 596 461 | 
             
                    prof_allocation_t* allocation_data = prof_allocation_get(allocation);
         | 
| 597 462 |  | 
| 598 | 
            -
                     | 
| 463 | 
            +
                    rb_st_insert(method_data->allocations_table, allocation_data->key, (st_data_t)allocation_data);
         | 
| 599 464 | 
             
                }
         | 
| 600 465 | 
             
                return data;
         | 
| 601 466 | 
             
            }
         | 
| @@ -603,28 +468,24 @@ prof_method_load(VALUE self, VALUE data) | |
| 603 468 | 
             
            void rp_init_method_info()
         | 
| 604 469 | 
             
            {
         | 
| 605 470 | 
             
                /* MethodInfo */
         | 
| 606 | 
            -
                cRpMethodInfo = rb_define_class_under(mProf, "MethodInfo",  | 
| 471 | 
            +
                cRpMethodInfo = rb_define_class_under(mProf, "MethodInfo", rb_cObject);
         | 
| 607 472 | 
             
                rb_undef_method(CLASS_OF(cRpMethodInfo), "new");
         | 
| 608 473 | 
             
                rb_define_alloc_func(cRpMethodInfo, prof_method_allocate);
         | 
| 609 474 |  | 
| 610 475 | 
             
                rb_define_method(cRpMethodInfo, "klass_name", prof_method_klass_name, 0);
         | 
| 611 476 | 
             
                rb_define_method(cRpMethodInfo, "klass_flags", prof_method_klass_flags, 0);
         | 
| 612 | 
            -
             | 
| 613 477 | 
             
                rb_define_method(cRpMethodInfo, "method_name", prof_method_name, 0);
         | 
| 614 | 
            -
             
         | 
| 615 | 
            -
                rb_define_method(cRpMethodInfo, "callers", prof_method_callers, 0);
         | 
| 616 | 
            -
                rb_define_method(cRpMethodInfo, "callees", prof_method_callees, 0);
         | 
| 617 | 
            -
                rb_define_method(cRpMethodInfo, "allocations", prof_method_allocations, 0);
         | 
| 618 478 |  | 
| 479 | 
            +
                rb_define_method(cRpMethodInfo, "call_trees", prof_method_call_trees, 0);
         | 
| 480 | 
            +
             | 
| 481 | 
            +
                rb_define_method(cRpMethodInfo, "allocations", prof_method_allocations, 0);
         | 
| 619 482 | 
             
                rb_define_method(cRpMethodInfo, "measurement", prof_method_measurement, 0);
         | 
| 620 | 
            -
             | 
| 483 | 
            +
             | 
| 621 484 | 
             
                rb_define_method(cRpMethodInfo, "source_file", prof_method_source_file, 0);
         | 
| 622 485 | 
             
                rb_define_method(cRpMethodInfo, "line", prof_method_line, 0);
         | 
| 623 486 |  | 
| 624 | 
            -
                rb_define_method(cRpMethodInfo, "root?", prof_method_root, 0);
         | 
| 625 487 | 
             
                rb_define_method(cRpMethodInfo, "recursive?", prof_method_recursive, 0);
         | 
| 626 | 
            -
                rb_define_method(cRpMethodInfo, "excluded?", prof_method_excluded, 0);
         | 
| 627 488 |  | 
| 628 489 | 
             
                rb_define_method(cRpMethodInfo, "_dump_data", prof_method_dump, 0);
         | 
| 629 490 | 
             
                rb_define_method(cRpMethodInfo, "_load_data", prof_method_load, 1);
         | 
| 630 | 
            -
            }
         | 
| 491 | 
            +
            }
         |