From 09b7dbabbffe538c6f911e8038a772b69f72867f Mon Sep 17 00:00:00 2001
From: Martin Karlgren <marty@roxen.com>
Date: Thu, 4 Jun 2015 22:59:17 +0200
Subject: [PATCH] count_memory: avoid visiting refs at all in negative
 lookahead mode.

---
 src/array.c      |  5 +++--
 src/constants.c  |  2 +-
 src/gc.c         |  4 ++++
 src/gc.h         | 10 ++++++++++
 src/mapping.c    |  7 ++++---
 src/multiset.c   |  7 ++++---
 src/object.c     | 44 +++++++++++++++++++++++---------------------
 src/pike_types.c |  2 +-
 src/program.c    |  2 +-
 src/stralloc.c   |  2 +-
 10 files changed, 52 insertions(+), 33 deletions(-)

diff --git a/src/array.c b/src/array.c
index ac765f289b..a0c89e02e5 100644
--- a/src/array.c
+++ b/src/array.c
@@ -2743,7 +2743,7 @@ void check_all_arrays(void)
 PMOD_EXPORT void visit_array (struct array *a, int action, void *extra)
 {
   visit_enter(a, T_ARRAY, extra);
-  switch (action) {
+  switch (action & VISIT_MODE_MASK) {
 #ifdef PIKE_DEBUG
     default:
       Pike_fatal ("Unknown visit action %d.\n", action);
@@ -2757,7 +2757,8 @@ PMOD_EXPORT void visit_array (struct array *a, int action, void *extra)
       break;
   }
 
-  if (a->type_field &
+  if (!(action & VISIT_NO_REFS) &&
+      a->type_field &
       (action & VISIT_COMPLEX_ONLY ? BIT_COMPLEX : BIT_REF_TYPES)) {
     size_t e, s = a->size;
     int ref_type = a->flags & ARRAY_WEAK_FLAG ? REF_TYPE_WEAK : REF_TYPE_NORMAL;
diff --git a/src/constants.c b/src/constants.c
index d09ed922df..70da823244 100644
--- a/src/constants.c
+++ b/src/constants.c
@@ -197,7 +197,7 @@ PMOD_EXPORT void quick_add_efun(const char *name, ptrdiff_t name_length,
 PMOD_EXPORT void visit_callable (struct callable *c, int action, void *extra)
 {
   visit_enter(c, T_STRUCT_CALLABLE, extra);
-  switch (action) {
+  switch (action & VISIT_MODE_MASK) {
 #ifdef PIKE_DEBUG
     default:
       Pike_fatal ("Unknown visit action %d.\n", action);
diff --git a/src/gc.c b/src/gc.c
index c1db83d65d..40103f8102 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -5750,6 +5750,10 @@ void f_count_memory (INT32 args)
       if (mc_ref_from->flags & MC_FLAG_INTERNAL) {
 	action = VISIT_COUNT_BYTES; /* Memory count this. */
 	MC_DEBUG_MSG (NULL, "enter with byte counting");
+	if (mc_lookahead < 0) {
+	  MC_DEBUG_MSG (NULL, "VISIT_NO_REFS mode");
+	  action |= VISIT_NO_REFS;
+	}
 
 	mc_ref_from->visit_fn (mc_ref_from->thing, action, mc_ref_from->extra);
 	count_visits++;
diff --git a/src/gc.h b/src/gc.h
index 70baabfd74..2e3ef562b1 100644
--- a/src/gc.h
+++ b/src/gc.h
@@ -683,6 +683,16 @@ PMOD_EXPORT extern visit_leave_cb *visit_leave;
  * mc_counted_bytes, then visit the refs. Never combined with
  * VISIT_COMPLEX_ONLY. */
 
+#define VISIT_MODE_MASK 0x0F
+/* Bitmask for visit mode selection. The rest is flags. */
+
+#define VISIT_NO_REFS 0x10
+/* Don't visit any refs. Typically set when lookahead is negative as
+   an optimization. */
+
+#define VISIT_FLAGS_MASK 0xF0
+/* Bitmask for visit flags. */
+
 /* Map between type and visit function for the standard ref types. */
 PMOD_EXPORT extern visit_thing_fn *const visit_fn_from_type[MAX_TYPE + 1];
 PMOD_EXPORT TYPE_T type_from_visit_fn (visit_thing_fn *fn);
diff --git a/src/mapping.c b/src/mapping.c
index 5126ba9c39..f8b1dcb40b 100644
--- a/src/mapping.c
+++ b/src/mapping.c
@@ -2528,7 +2528,7 @@ static void visit_mapping_data (struct mapping_data *md, int action,
 				void *extra)
 {
   visit_enter(md, T_MAPPING_DATA, extra);
-  switch (action) {
+  switch (action & VISIT_MODE_MASK) {
 #ifdef PIKE_DEBUG
     default:
       Pike_fatal ("Unknown visit action %d.\n", action);
@@ -2541,7 +2541,8 @@ static void visit_mapping_data (struct mapping_data *md, int action,
       break;
   }
 
-  if ((md->ind_types | md->val_types) &
+  if (!(action & VISIT_NO_REFS) &&
+      (md->ind_types | md->val_types) &
       (action & VISIT_COMPLEX_ONLY ? BIT_COMPLEX : BIT_REF_TYPES)) {
     int ind_ref_type =
       md->flags & MAPPING_WEAK_INDICES ? REF_TYPE_WEAK : REF_TYPE_NORMAL;
@@ -2560,7 +2561,7 @@ static void visit_mapping_data (struct mapping_data *md, int action,
 PMOD_EXPORT void visit_mapping (struct mapping *m, int action, void *extra)
 {
   visit_enter(m, T_MAPPING, extra);
-  switch (action) {
+  switch (action & VISIT_MODE_MASK) {
 #ifdef PIKE_DEBUG
     default:
       Pike_fatal ("Unknown visit action %d.\n", action);
diff --git a/src/multiset.c b/src/multiset.c
index 5ac958851f..02a5c8a345 100644
--- a/src/multiset.c
+++ b/src/multiset.c
@@ -3472,7 +3472,7 @@ static void visit_multiset_data (struct multiset_data *msd, int action,
 				 void *extra)
 {
   visit_enter(msd, T_MULTISET_DATA, extra);
-  switch (action) {
+  switch (action & VISIT_MODE_MASK) {
 #ifdef PIKE_DEBUG
     default:
       Pike_fatal ("Unknown visit action %d.\n", action);
@@ -3487,7 +3487,8 @@ static void visit_multiset_data (struct multiset_data *msd, int action,
       break;
   }
 
-  if (msd->root &&
+  if (!(action & VISIT_NO_REFS) &&
+      msd->root &&
       ((msd->ind_types | msd->val_types) &
        (action & VISIT_COMPLEX_ONLY ? BIT_COMPLEX : BIT_REF_TYPES))) {
     int ind_ref_type =
@@ -3515,7 +3516,7 @@ static void visit_multiset_data (struct multiset_data *msd, int action,
 PMOD_EXPORT void visit_multiset (struct multiset *l, int action, void *extra)
 {
   visit_enter(l, T_MULTISET, extra);
-  switch (action) {
+  switch (action & VISIT_MODE_MASK) {
 #ifdef PIKE_DEBUG
     default:
       Pike_fatal ("Unknown visit action %d.\n", action);
diff --git a/src/object.c b/src/object.c
index 0c486cfb75..98e9f6ce33 100644
--- a/src/object.c
+++ b/src/object.c
@@ -2105,7 +2105,7 @@ PMOD_EXPORT void visit_object (struct object *o, int action, void *extra)
   if (o->next == o) return; /* Fake object used by compiler */
 
   visit_enter(o, T_OBJECT, extra);
-  switch (action) {
+  switch (action & VISIT_MODE_MASK) {
 #ifdef PIKE_DEBUG
     default:
       Pike_fatal ("Unknown visit action %d.\n", action);
@@ -2133,31 +2133,32 @@ PMOD_EXPORT void visit_object (struct object *o, int action, void *extra)
 
     for (e = p->num_inherits - 1; e >= 0; e--) {
       struct program *inh_prog = inh[e].prog;
-      unsigned INT16 *inh_prog_var_idxs = inh_prog->variable_index;
-      struct identifier *inh_prog_ids = inh_prog->identifiers;
-      char *inh_storage = storage + inh[e].storage_offset;
-
-      int q, num_vars = (int) inh_prog->num_variable_index;
-
-      for (q = 0; q < num_vars; q++) {
-	int d = inh_prog_var_idxs[q];
-	struct identifier *id = inh_prog_ids + d;
-	int id_flags = id->identifier_flags;
-	int rtt = id->run_time_type;
-	void *var;
-	union anything *u;
+      if (!(action & VISIT_NO_REFS)) {
+	unsigned INT16 *inh_prog_var_idxs = inh_prog->variable_index;
+	struct identifier *inh_prog_ids = inh_prog->identifiers;
+	char *inh_storage = storage + inh[e].storage_offset;
+
+	int q, num_vars = (int) inh_prog->num_variable_index;
 
-	if (IDENTIFIER_IS_ALIAS (id_flags))
-	  continue;
+	for (q = 0; q < num_vars; q++) {
+	  int d = inh_prog_var_idxs[q];
+	  struct identifier *id = inh_prog_ids + d;
+	  int id_flags = id->identifier_flags;
+	  int rtt = id->run_time_type;
+	  void *var;
+	  union anything *u;
 
-	var = inh_storage + id->func.offset;
-	u = (union anything *) var;
+	  if (IDENTIFIER_IS_ALIAS (id_flags))
+	    continue;
+
+	  var = inh_storage + id->func.offset;
+	  u = (union anything *) var;
 #ifdef DEBUG_MALLOC
-	if (REFCOUNTED_TYPE(rtt))
-	  debug_malloc_touch (u->ptr);
+	  if (REFCOUNTED_TYPE(rtt))
+	    debug_malloc_touch (u->ptr);
 #endif
 
-	switch (rtt) {
+	  switch (rtt) {
 	  case T_MIXED: {
 	    struct svalue *s = (struct svalue *) var;
 	    dmalloc_touch_svalue (s);
@@ -2209,6 +2210,7 @@ PMOD_EXPORT void visit_object (struct object *o, int action, void *extra)
 	  default:
 	    Pike_fatal ("Invalid runtime type %d.\n", rtt);
 #endif
+	  }
 	}
       }
 
diff --git a/src/pike_types.c b/src/pike_types.c
index ed6fad4e19..6185092f7e 100644
--- a/src/pike_types.c
+++ b/src/pike_types.c
@@ -8956,7 +8956,7 @@ PMOD_EXPORT void *find_type(struct pike_type *t,
 PMOD_EXPORT void visit_type (struct pike_type *t, int action, void *extra)
 {
   visit_enter(t, PIKE_T_TYPE, extra);
-  switch (action) {
+  switch (action & VISIT_MODE_MASK) {
 #ifdef PIKE_DEBUG
     default:
       Pike_fatal ("Unknown visit action %d.\n", action);
diff --git a/src/program.c b/src/program.c
index 5a82931949..6c57a87661 100644
--- a/src/program.c
+++ b/src/program.c
@@ -11042,7 +11042,7 @@ void cleanup_program(void)
 PMOD_EXPORT void visit_program (struct program *p, int action, void *extra)
 {
   visit_enter(p, T_PROGRAM, extra);
-  switch (action) {
+  switch (action & VISIT_MODE_MASK) {
 #ifdef PIKE_DEBUG
     default:
       Pike_fatal ("Unknown visit action %d.\n", action);
diff --git a/src/stralloc.c b/src/stralloc.c
index db28194f1c..f22bd94e9b 100644
--- a/src/stralloc.c
+++ b/src/stralloc.c
@@ -2242,7 +2242,7 @@ void count_memory_in_strings(size_t *num, size_t *size)
 PMOD_EXPORT void visit_string (struct pike_string *s, int action, void *extra)
 {
   visit_enter(s, T_STRING, extra);
-  switch (action) {
+  switch (action & VISIT_MODE_MASK) {
 #ifdef PIKE_DEBUG
     default:
       Pike_fatal ("Unknown visit action %d.\n", action);
-- 
GitLab