From 5ca7b541e774d0c5ce2850587b3666017e6fb33d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Walld=C3=A9n?= <jonasw@roxen.com>
Date: Sat, 7 Jan 2012 03:36:30 +0100
Subject: [PATCH] Fix profiling of recursive functions by tracking recursion
 level. Fixes [bug 5131].

---
 src/apply_low.h           | 1 +
 src/encode.c              | 1 +
 src/interpret.c           | 3 ++-
 src/interpret.h           | 3 ++-
 src/interpret_functions.h | 5 ++++-
 src/program.c             | 4 ++++
 src/program.h             | 1 +
 7 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/src/apply_low.h b/src/apply_low.h
index 7cba077648..4a408d1e8f 100644
--- a/src/apply_low.h
+++ b/src/apply_low.h
@@ -218,6 +218,7 @@
 
 #ifdef PROFILING
       function->num_calls++;
+      function->recur_depth++;
 #endif
   
       if(function->func.offset == -1) {
diff --git a/src/encode.c b/src/encode.c
index e94e580511..78f4877adc 100644
--- a/src/encode.c
+++ b/src/encode.c
@@ -4442,6 +4442,7 @@ static void decode_value2(struct decode_data *data)
 #ifdef PROFILING
 		id.self_time=0;
 		id.num_calls=0;
+		id.recur_depth=0;
 		id.total_time=0;
 #endif
 
diff --git a/src/interpret.c b/src/interpret.c
index c4d520168b..e2cb5eb9ab 100644
--- a/src/interpret.c
+++ b/src/interpret.c
@@ -2379,7 +2379,8 @@ void unlink_previous_frame(void)
       Pike_interpreter.accounted_time - current->children_base;
     struct identifier *function =
       current->context->prog->identifiers + current->ident;
-    function->total_time += total_time;
+    if (!function->recur_depth)
+      function->total_time += total_time;
     total_time -= child_time;
     function->self_time += total_time;
     Pike_interpreter.accounted_time += total_time;
diff --git a/src/interpret.h b/src/interpret.h
index 9c9bbf3de0..7b00791b50 100644
--- a/src/interpret.h
+++ b/src/interpret.h
@@ -626,7 +626,8 @@ PMOD_EXPORT extern const char msg_pop_neg[];
       Pike_interpreter.accounted_time += self_time;			\
       /* FIXME: Can context->prog be NULL? */				\
       function = _fp_->context->prog->identifiers + _fp_->ident;	\
-      function->total_time += time_passed;				\
+      if (!--function->recur_depth)					\
+	function->total_time += time_passed;				\
       function->self_time += self_time;					\
     });									\
   LOW_POP_PIKE_FRAME (_fp_);						\
diff --git a/src/interpret_functions.h b/src/interpret_functions.h
index bb8228964a..fa2cd68a6e 100644
--- a/src/interpret_functions.h
+++ b/src/interpret_functions.h
@@ -2499,11 +2499,14 @@ OPCODE1(F_LTOSVAL_CALL_BUILTIN_AND_ASSIGN_POP,
   new_frame->context = Pike_fp->context;				   \
 									   \
   DO_IF_PROFILING({							   \
+      struct identifier *func;						   \
       new_frame->start_time =						   \
 	get_cpu_time() - Pike_interpreter.unlocked_time;		   \
       new_frame->ident = Pike_fp->ident;				   \
       new_frame->children_base = Pike_interpreter.accounted_time;	   \
-      new_frame->context->prog->identifiers[new_frame->ident].num_calls++;  \
+      func = new_frame->context->prog->identifiers + new_frame->ident;	   \
+      func->num_calls++;						   \
+      func->recur_depth++;						   \
       DO_IF_PROFILING_DEBUG({						   \
 	  fprintf(stderr, "%p{: Push at %" PRINT_CPU_TIME		   \
 		  " %" PRINT_CPU_TIME "\n",				   \
diff --git a/src/program.c b/src/program.c
index c0fc1e87e6..8488fe7929 100644
--- a/src/program.c
+++ b/src/program.c
@@ -4937,6 +4937,7 @@ int low_define_alias(struct pike_string *name, struct pike_type *type,
 #ifdef PROFILING
   dummy.self_time=0;
   dummy.num_calls=0;
+  dummy.recur_depth=0;
   dummy.total_time=0;
 #endif
 
@@ -5067,6 +5068,7 @@ int low_define_variable(struct pike_string *name,
 #ifdef PROFILING
   dummy.self_time=0;
   dummy.num_calls=0;
+  dummy.recur_depth=0;
   dummy.total_time=0;
 #endif
 
@@ -5520,6 +5522,7 @@ PMOD_EXPORT int add_constant(struct pike_string *name,
 #ifdef PROFILING
   dummy.self_time=0;
   dummy.num_calls=0;
+  dummy.recur_depth=0;
   dummy.total_time=0;
 #endif
 
@@ -5739,6 +5742,7 @@ INT32 define_function(struct pike_string *name,
 #ifdef PROFILING
   fun.self_time=0;
   fun.num_calls=0;
+  fun.recur_depth=0;
   fun.total_time=0;
 #endif
 
diff --git a/src/program.h b/src/program.h
index ce1187758a..8e62ad16ef 100644
--- a/src/program.h
+++ b/src/program.h
@@ -288,6 +288,7 @@ struct identifier
   unsigned INT16 opt_flags;		/* OPT_??? */
 #ifdef PROFILING
   unsigned INT32 num_calls;		/* Total number of calls. */
+  unsigned INT32 recur_depth;		/* Recursion depth during timing. */
   cpu_time_t total_time;		/* Total time with children. */
   cpu_time_t self_time;			/* Total time excluding children. */
 #endif /* PROFILING */
-- 
GitLab