sourcepawn/compiler/sctracker.c
author David Anderson <dvander@alliedmods.net>
Fri Nov 03 06:14:43 2006 +0000 (2006-11-03)
changeset 132 dabef847cd2c
parent 118 0cfeb76486a2
child 167 4db3481b6db7
permissions -rw-r--r--
Expanded weak function pointers with type checking
Added function typing enumeration
     1 #include <malloc.h>
     2 #include <string.h>
     3 #include <assert.h>
     4 #include "sc.h"
     5 #include "sctracker.h"
     6 
     7 memuse_list_t *heapusage = NULL;
     8 memuse_list_t *stackusage = NULL;
     9 funcenum_t *firstenum = NULL;
    10 funcenum_t *lastenum = NULL;
    11 
    12 void funcenums_free()
    13 {
    14 	funcenum_t *e, *next;
    15 
    16 	e = firstenum;
    17 	while (e)
    18 	{
    19 		functag_t *tag, *nexttag;
    20 		tag = e->first;
    21 		while (tag)
    22 		{
    23 			nexttag = tag->next;
    24 			free(tag);
    25 			tag = nexttag;
    26 		}
    27 		next = e->next;
    28 		free(e);
    29 		e = next;
    30 	}
    31 
    32 	firstenum = NULL;
    33 	lastenum = NULL;
    34 }
    35 
    36 funcenum_t *funcenums_find_byval(int value)
    37 {
    38 	funcenum_t *e = firstenum;
    39 
    40 	while (e)
    41 	{
    42 		if (e->value == value)
    43 		{
    44 			return e;
    45 		}
    46 		e = e->next;
    47 	}
    48 
    49 	return NULL;
    50 }
    51 
    52 funcenum_t *funcenums_add(const char *name)
    53 {
    54 	funcenum_t *e = (funcenum_t *)malloc(sizeof(funcenum_t));
    55 
    56 	memset(e, 0, sizeof(funcenum_t));
    57 
    58 	if (firstenum == NULL)
    59 	{
    60 		firstenum = e;
    61 		lastenum = e;
    62 	} else {
    63 		lastenum->next = e;
    64 		lastenum = e;
    65 	}
    66 
    67 	strcpy(e->name, name);
    68 	e->value = pc_addfunctag((char *)name);
    69 
    70 	return e;
    71 }
    72 
    73 functag_t *functags_add(funcenum_t *en, functag_t *src)
    74 {
    75 	functag_t *t = (functag_t *)malloc(sizeof(functag_t));
    76 	
    77 	memcpy(t, src, sizeof(functag_t));
    78 
    79 	t->next = NULL;
    80 
    81 	if (en->first == NULL)
    82 	{
    83 		en->first = t;
    84 		en->last = t;
    85 	} else {
    86 		en->last->next = t;
    87 		en->last = t;
    88 	}
    89 
    90 	return t;
    91 }
    92 
    93 /**
    94  * Creates a new mem usage tracker entry
    95  */
    96 void _push_memlist(memuse_list_t **head)
    97 {
    98   memuse_list_t *newlist = (memuse_list_t *)malloc(sizeof(memuse_list_t));
    99   if (*head != NULL)
   100   {
   101     newlist->list_id = (*head)->list_id + 1;
   102   } else {
   103     newlist->list_id = 0;
   104   }
   105   newlist->prev = *head;
   106   newlist->head = NULL;
   107   *head = newlist;
   108 }
   109 
   110 /**
   111  * Pops a heap list but does not free it.
   112  */
   113 memuse_list_t *_pop_save_memlist(memuse_list_t **head)
   114 {
   115   memuse_list_t *oldlist = *head;
   116   *head = (*head)->prev;
   117   return oldlist;
   118 }
   119 
   120 /**
   121  * Marks a memory usage on a memory list
   122  */
   123 int _mark_memlist(memuse_list_t *head, int type, int size)
   124 {
   125   memuse_t *use;
   126   if (type==MEMUSE_STATIC && size==0)
   127   {
   128     return 0;
   129   }
   130   use=head->head;
   131   if (use && (type==MEMUSE_STATIC) 
   132       && (use->type == type))
   133   {
   134     use->size += size;
   135   } else {
   136     use=(memuse_t *)malloc(sizeof(memuse_t));
   137     use->type=type;
   138     use->size=size;
   139     use->prev=head->head;
   140     head->head=use;
   141   }
   142   return size;
   143 }
   144 
   145 void _reset_memlist(memuse_list_t **head)
   146 {
   147   memuse_list_t *curlist = *head;
   148   memuse_list_t *tmplist;
   149   while (curlist) {
   150     memuse_t *curuse = curlist->head;
   151     memuse_t *tmpuse;
   152     while (curuse) {
   153       tmpuse = curuse->prev;
   154       free(curuse);
   155       curuse = tmpuse;
   156     }
   157     tmplist = curlist->prev;
   158     free(curlist);
   159     curlist = tmplist;
   160   }
   161   *head = NULL;
   162 }
   163 
   164 
   165 /**
   166  * Wrapper for pushing the heap list
   167  */
   168 void pushheaplist()
   169 {
   170   _push_memlist(&heapusage);
   171 }
   172 
   173 /**
   174  * Wrapper for popping and saving the heap list
   175  */
   176 memuse_list_t *popsaveheaplist()
   177 {
   178   return _pop_save_memlist(&heapusage);
   179 }
   180 
   181 /**
   182  * Wrapper for marking the heap
   183  */
   184 int markheap(int type, int size)
   185 {
   186   return _mark_memlist(heapusage, type, size);
   187 }
   188 
   189 /**
   190  * Wrapper for pushing the stack list
   191  */
   192 void pushstacklist()
   193 {
   194   _push_memlist(&stackusage);
   195 }
   196 
   197 /**
   198  * Wrapper for marking the stack
   199  */
   200 int markstack(int type, int size)
   201 {
   202   return _mark_memlist(stackusage, type, size);
   203 }
   204 
   205 /**
   206  * Generates code to free all heap allocations on a tracker
   207  */
   208 void _heap_freeusage(memuse_list_t *heap, int dofree)
   209 {
   210   memuse_t *cur=heap->head;
   211   memuse_t *tmp;
   212   while (cur)
   213   {
   214     if (cur->type == MEMUSE_STATIC)
   215 	{
   216       modheap((-1)*cur->size*sizeof(cell));
   217     } else {
   218       modheap_i();
   219     }
   220     if (dofree)
   221     {
   222       tmp=cur->prev;
   223       free(cur);
   224       cur=tmp;
   225     } else {
   226       cur=cur->prev;
   227     }
   228   }
   229   if (dofree)
   230   {
   231     heap->head=NULL;
   232   }
   233 }
   234 
   235 void _stack_genusage(memuse_list_t *stack, int dofree)
   236 {
   237   memuse_t *cur = stack->head;
   238   memuse_t *tmp;
   239   while (cur)
   240   {
   241     if (cur->type == MEMUSE_DYNAMIC)
   242 	{
   243       /* no idea yet */
   244       assert(0);
   245 	} else {
   246       modstk(cur->size * sizeof(cell));
   247 	}
   248 	if (dofree)
   249 	{
   250       tmp = cur->prev;
   251       free(cur);
   252       cur = tmp;
   253 	} else {
   254       cur = cur->prev;
   255 	}
   256   }
   257   if (dofree)
   258   {
   259     stack->head = NULL;
   260   }
   261 }
   262 
   263 /**
   264  * Pops a heap list and frees it.
   265  */
   266 void popheaplist()
   267 {
   268   memuse_list_t *oldlist;
   269   assert(heapusage!=NULL);
   270 
   271   _heap_freeusage(heapusage, 1);
   272   assert(heapusage->head==NULL);
   273 
   274   oldlist=heapusage->prev;
   275   free(heapusage);
   276   heapusage=oldlist;
   277 }
   278 
   279 void genstackfree(int stop_id)
   280 {
   281   memuse_list_t *curlist = stackusage;
   282   while (curlist && curlist->list_id > stop_id)
   283   {
   284     _stack_genusage(curlist, 0);
   285     curlist = curlist->prev;
   286   }
   287 }
   288 
   289 void genheapfree(int stop_id)
   290 {
   291   memuse_list_t *curlist = heapusage;
   292   while (curlist && curlist->list_id > stop_id)
   293   {
   294     _heap_freeusage(curlist, 0);
   295     curlist = curlist->prev;
   296   }
   297 }
   298 
   299 void popstacklist()
   300 {
   301   memuse_list_t *oldlist;
   302   assert(stackusage != NULL);
   303 
   304   _stack_genusage(stackusage, 1);
   305   assert(stackusage->head==NULL);
   306 
   307   oldlist = stackusage->prev;
   308   free(stackusage);
   309   stackusage = oldlist;
   310 }
   311 
   312 void resetstacklist()
   313 {
   314   _reset_memlist(&stackusage);
   315 }
   316 
   317 void resetheaplist()
   318 {
   319   _reset_memlist(&heapusage);
   320 }