2007-03-31
2007-03-31 21:39:45 by Henrik Grubbström (Grubba) <grubba@grubba.org>
-
16c569cfefb182167d7975137ca08e1e24adcc5c
(277 lines)
(+270/-7)
[
Show
| Annotate
]
Branch: 7.9
Fixed leak in handling of the splice operator in new_check_call().
Added placeholders for gc hooks.
Rev: src/pike_types.c:1.273
2:
|| This file is part of Pike. For copyright information see COPYRIGHT.
|| Pike is distributed under GPL, LGPL and MPL. See the file COPYING
|| for more information.
- || $Id: pike_types.c,v 1.272 2007/03/31 15:08:42 grubba Exp $
+ || $Id: pike_types.c,v 1.273 2007/03/31 21:39:45 grubba Exp $
*/
#include "global.h"
26:
#include "main.h"
#include "opcodes.h"
#include "cyclic.h"
+ #include "gc.h"
#include "block_alloc.h"
#ifdef PIKE_DEBUG
5341: Inside #if defined(PIKE_DEBUG)
if (l_flag>2) {
fprintf(stderr, " Checking argument #%d... ", *argno);
simple_describe_type(args->type);
- fprintf(stderr, " fun_type: ");
+ fprintf(stderr, "\n fun_type: ");
simple_describe_type(fun_type);
}
- #endif /* PIK_DEBUG */
+ #endif /* PIKE_DEBUG */
if (args->token == F_PUSH_ARRAY) {
struct pike_type *prev = NULL;
int cnt = 256;
/* This token can expand to anything between zero and MAX_ARGS args. */
-
+ #ifdef PIKE_DEBUG
+ if (l_flag>2) {
+ fprintf(stderr, "\n The argument is a splice operator.");
+ }
+ #endif /* PIKE_DEBUG */
+
/* Loop until we get a stable fun_type, or it's an invalid argument. */
- while ((tmp = low_new_check_call(fun_type, args->type, 0)) &&
+ while ((tmp = low_new_check_call(debug_malloc_pass(fun_type),
+ debug_malloc_pass(args->type), 0)) &&
(tmp != prev) && --cnt) {
-
+
+ #ifdef PIKE_DEBUG
+ if (l_flag>4) {
+ fprintf(stderr, "\n sub_result_type: ");
+ simple_describe_type(tmp);
+ }
+ #endif /* PIKE_DEBUG */
+
if (prev) {
free_type(prev);
}
prev = tmp;
- tmp = or_pike_types(fun_type, prev, 1);
+ tmp = dmalloc_touch(struct pike_type *,
+ or_pike_types(debug_malloc_pass(fun_type),
+ debug_malloc_pass(prev), 1));
+ #ifdef PIKE_DEBUG
+ if (l_flag>4) {
+ fprintf(stderr, "\n joined_type: ");
+ simple_describe_type(tmp);
+ }
+ #endif /* PIKE_DEBUG */
+
free_type(fun_type);
fun_type = tmp;
}
- if (cnt == 256) {
- yywarning("The slice operator argument must be an empty array.");
+ if (prev) {
+ free_type(prev);
}
-
+ if (tmp) {
+ free_type(tmp);
+ } else if (cnt == 256) {
+ yywarning("The splice operator argument must be an empty array.");
+ } else {
+ yywarning("The splice operator argument has a max length of %d.",
+ 256-cnt);
+ }
+
+ #ifdef PIKE_DEBUG
+ if (l_flag>2) {
+ fprintf(stderr, "\n result: ");
+ simple_describe_type(fun_type);
+ fprintf(stderr, " OK.\n");
+ }
+ #endif /* PIKE_DEBUG */
+
return fun_type;
} else if ((tmp = low_new_check_call(fun_type, args->type, 0))) {
/* OK. */
6171:
return free_buf(&save_buf);
}
+ #if 0
+ #ifdef DEBUG_MALLOC
+ static void gc_mark_external_types(struct callback *cb, void *a, void *b)
+ {
+ GC_ENTER(pike_type_hash, PIKE_T_TYPE) {
+ if (string0_type_string)
+ gc_mark_external(string0_type_string, " as string0_type_string");
+ if (string_type_string)
+ gc_mark_external(string_type_string, " as string_type_string");
+ if (int_type_string)
+ gc_mark_external(int_type_string, " as int_type_string");
+ if (object_type_string)
+ gc_mark_external(object_type_string, " as object_type_string");
+ if (program_type_string)
+ gc_mark_external(program_type_string, " as program_type_string");
+ if (float_type_string)
+ gc_mark_external(float_type_string, " as float_type_string");
+ if (mixed_type_string)
+ gc_mark_external(mixed_type_string, " as mixed_type_string");
+ if (array_type_string)
+ gc_mark_external(array_type_string, " as array_type_string");
+ if (multiset_type_string)
+ gc_mark_external(multiset_type_string, " as multiset_type_string");
+ if (mapping_type_string)
+ gc_mark_external(mapping_type_string, " as mapping_type_string");
+ if (function_type_string)
+ gc_mark_external(function_type_string, " as function_type_string");
+ if (type_type_string)
+ gc_mark_external(type_type_string, " as type_type_string");
+ if (void_type_string)
+ gc_mark_external(void_type_string, " as void_type_string");
+ if (zero_type_string)
+ gc_mark_external(zero_type_string, " as zero_type_string");
+ if (any_type_string)
+ gc_mark_external(any_type_string, " as any_type_string");
+ if (weak_type_string)
+ gc_mark_external(weak_type_string, " as weak_type_string");
+ } GC_LEAVE;
+ }
+
+ static struct callback *dmalloc_gc_callback = NULL;
+ #endif /* DEBUG_MALLOC */
+ #endif /* 0 */
+
void init_types(void)
{
/* Initialize hashtable here. */
6197:
any_type_string = CONSTTYPE(tOr(tVoid,tMix));
weak_type_string = CONSTTYPE(tOr4(tArray,tMultiset,tMapping,
tFuncV(tNone,tZero,tOr(tMix,tVoid))));
+ //add_ref(weak_type_string); /* LEAK */
+
+ #if 0
+ #ifdef DEBUG_MALLOC
+ dmalloc_gc_callback = add_gc_callback(gc_mark_external_types, NULL, NULL);
+ #endif /* DEBUG_MALLOC */
+ #endif /* 0 */
}
void cleanup_pike_types(void)
6211:
#endif /* DEBUG_MALLOC */
free_type(string0_type_string);
+ string0_type_string = NULL;
free_type(string_type_string);
-
+ string_type_string = NULL;
free_type(int_type_string);
-
+ int_type_string = NULL;
free_type(float_type_string);
-
+ float_type_string = NULL;
free_type(function_type_string);
-
+ function_type_string = NULL;
free_type(object_type_string);
-
+ object_type_string = NULL;
free_type(program_type_string);
-
+ program_type_string = NULL;
free_type(array_type_string);
-
+ array_type_string = NULL;
free_type(multiset_type_string);
-
+ multiset_type_string = NULL;
free_type(mapping_type_string);
-
+ mapping_type_string = NULL;
free_type(type_type_string);
-
+ type_type_string = NULL;
free_type(mixed_type_string);
-
+ mixed_type_string = NULL;
free_type(void_type_string);
-
+ void_type_string = NULL;
free_type(zero_type_string);
-
+ zero_type_string = NULL;
free_type(any_type_string);
-
+ any_type_string = NULL;
free_type(weak_type_string);
-
+ weak_type_string = NULL;
+
+ #if 0
+ #ifdef DEBUG_MALLOC
+ remove_callback(dmalloc_gc_callback);
+ #endif /* DEBUG_MALLOC */
+ #endif /* 0 */
}
void cleanup_pike_type_table(void)
6244:
* It's needed for dmalloc to survive.
*/
pike_type_hash_size = 0;
+ #if 0
#ifdef DO_PIKE_CLEANUP
free_all_pike_type_blocks();
#endif /* DO_PIKE_CLEANUP */
-
+ #endif /* 0 */
}
-
+
+ #if 0
+ #ifdef PIKE_DEBUG
+
+ void gc_mark_type_as_referenced(struct pike_type *t)
+ {
+ if (gc_mark(t)) {
+ GC_ENTER(t, PIKE_T_TYPE) {
+ switch(t->type) {
+ case PIKE_T_SCOPE:
+ case T_ASSIGN:
+ case PIKE_T_NAME:
+ if (t->cdr) gc_mark_type_as_referenced(t->cdr);
+ break;
+ case PIKE_T_FUNCTION:
+ case T_MANY:
+ case PIKE_T_RING:
+ case PIKE_T_TUPLE:
+ case PIKE_T_MAPPING:
+ case T_OR:
+ case T_AND:
+ if (t->cdr) gc_mark_type_as_referenced(t->cdr);
+ /* FALL_THOUGH */
+ case PIKE_T_ARRAY:
+ case PIKE_T_MULTISET:
+ case T_NOT:
+ case PIKE_T_TYPE:
+ case PIKE_T_PROGRAM:
+ if (t->car) gc_mark_type_as_referenced(t->car);
+ break;
+ }
+ } GC_LEAVE;
+ }
+ }
+
+ unsigned gc_touch_all_types(void)
+ {
+ size_t e;
+ unsigned n = 0;
+ if (!pike_type_hash) return 0;
+ for(e=0;e<pike_type_hash_size;e++)
+ {
+ struct pike_type *t;
+ for(t = pike_type_hash[e]; t; t=t->next) debug_gc_touch(t), n++;
+ }
+ return n;
+ }
+
+ void gc_mark_all_types(void)
+ {
+ size_t e;
+ if(!pike_type_hash) return;
+ for(e=0;e<pike_type_hash_size;e++)
+ {
+ struct pike_type *t;
+ for(t=pike_type_hash[e]; t; t=t->next) {
+ if (gc_is_referenced(t)) {
+ gc_mark_type_as_referenced(t);
+ }
+ }
+ }
+ }
+
+ size_t gc_free_all_unreferenced_types(void)
+ {
+ size_t unreferenced = 0;
+ size_t e;
+ for (e = 0; e < pike_type_hash_size; e++) {
+ struct pike_type *t;
+ loop:
+ for (t = pike_type_hash[e]; t; t = t->next) {
+ struct marker *m = find_marker(t);
+ if (!m) continue;
+ if ((m->flags & GC_GOT_EXTRA_REF) == GC_GOT_EXTRA_REF) {
+ if (gc_do_free(t)) {
+ free_type(t);
+ unreferenced++;
+ /* The hash table may have been modified! */
+ goto loop;
+ }
+ }
+ }
+ }
+ for (e = 0; e < pike_type_hash_size; e++) {
+ struct pike_type *t;
+ for (t = pike_type_hash[e]; t; t = t->next) {
+ struct marker *m = find_marker(t);
+ if (!m) continue;
+ if ((m->flags & GC_GOT_EXTRA_REF) == GC_GOT_EXTRA_REF) {
+ fprintf(stderr, "There's still an extra ref to ");
+ simple_describe_type(t);
+ fprintf(stderr, "\n");
+ }
+ }
+ }
+ return unreferenced;
+ }
+
+ void real_gc_cycle_check_type(struct pike_type *t, int weak)
+ {
+ GC_CYCLE_ENTER(t, PIKE_T_TYPE, weak) {
+ switch(t->type) {
+ case PIKE_T_SCOPE:
+ case T_ASSIGN:
+ case PIKE_T_NAME:
+ if (t->cdr) gc_cycle_check_type(t->cdr, 0);
+ break;
+ case PIKE_T_FUNCTION:
+ case T_MANY:
+ case PIKE_T_RING:
+ case PIKE_T_TUPLE:
+ case PIKE_T_MAPPING:
+ case T_OR:
+ case T_AND:
+ if (t->cdr) gc_cycle_check_type(t->cdr, 0);
+ /* FALL_THOUGH */
+ case PIKE_T_ARRAY:
+ case PIKE_T_MULTISET:
+ case T_NOT:
+ case PIKE_T_TYPE:
+ case PIKE_T_PROGRAM:
+ if (t->car) gc_cycle_check_type(t->car, 0);
+ break;
+ }
+ } GC_CYCLE_LEAVE;
+ }
+
+ void gc_cycle_check_all_types(void)
+ {
+ #if 0
+ size_t e;
+ if(!pike_type_hash) return;
+ for(e=0;e<pike_type_hash_size;e++)
+ {
+ struct pike_type *t;
+ for(t=pike_type_hash[e]; t; t=t->next) {
+ real_gc_cycle_check_type(t, 0);
+ gc_cycle_run_queue();
+ }
+ }
+ #endif
+ }
+
+ #endif /* PIKE_DEBUG */
+ #endif /* 0 */