sourcepawn/compiler/sctracker.c
author Nicholas Hastings <skamonkey@gmail.com>
Mon Feb 08 19:57:20 2010 -0800 (2010-02-08)
changeset 2914 bf5f9aa53abe
parent 2471 194be299b700
permissions -rw-r--r--
Fixed FindEntityByClassname crash in Synergy (bug 4235, r=dvander).
dvander@2471
     1
#include <stdlib.h>
ds@1952
     2
#include <string.h>
ds@1952
     3
#include <assert.h>
ds@1952
     4
#include "sc.h"
ds@1952
     5
#include "sctracker.h"
ds@1952
     6
ds@1952
     7
memuse_list_t *heapusage = NULL;
ds@1952
     8
memuse_list_t *stackusage = NULL;
ds@1952
     9
funcenum_t *firstenum = NULL;
ds@1952
    10
funcenum_t *lastenum = NULL;
ds@1952
    11
pstruct_t *firststruct = NULL;
ds@1952
    12
pstruct_t *laststruct = NULL;
ds@1952
    13
ds@1952
    14
structarg_t *pstructs_getarg(pstruct_t *pstruct, const char *member)
ds@1952
    15
{
ds@1952
    16
	int i;
ds@1952
    17
ds@1952
    18
	for (i=0; i<pstruct->argcount; i++)
ds@1952
    19
	{
ds@1952
    20
		if (strcmp(pstruct->args[i]->name, member) == 0)
ds@1952
    21
		{
ds@1952
    22
			return pstruct->args[i];
ds@1952
    23
		}
ds@1952
    24
	}
ds@1952
    25
ds@1952
    26
	return NULL;
ds@1952
    27
}
ds@1952
    28
ds@1952
    29
pstruct_t *pstructs_add(const char *name)
ds@1952
    30
{
ds@1952
    31
	pstruct_t *p = (pstruct_t *)malloc(sizeof(pstruct_t));
ds@1952
    32
	
ds@1952
    33
	memset(p, 0, sizeof(pstruct_t));
ds@1952
    34
	strcpy(p->name, name);
ds@1952
    35
	
ds@1952
    36
	if (!firststruct)
ds@1952
    37
	{
ds@1952
    38
		firststruct = p;
ds@1952
    39
		laststruct = p;
ds@1952
    40
	} else {
ds@1952
    41
		laststruct->next = p;
ds@1952
    42
		laststruct = p;
ds@1952
    43
	}
ds@1952
    44
ds@1952
    45
	return p;
ds@1952
    46
}
ds@1952
    47
ds@1952
    48
void pstructs_free()
ds@1952
    49
{
ds@1952
    50
	pstruct_t *p, *next;
ds@1952
    51
ds@1952
    52
	p = firststruct;
ds@1952
    53
	while (p)
ds@1952
    54
	{
ds@1952
    55
		while (p->argcount--)
ds@1952
    56
		{
ds@1952
    57
			free(p->args[p->argcount]);
ds@1952
    58
		}
ds@1952
    59
		free(p->args);
ds@1952
    60
		next = p->next;
ds@1952
    61
		free(p);
ds@1952
    62
		p = next;
ds@1952
    63
	}
ds@1952
    64
	firststruct = NULL;
ds@1952
    65
	laststruct = NULL;
ds@1952
    66
}
ds@1952
    67
ds@1952
    68
pstruct_t *pstructs_find(const char *name)
ds@1952
    69
{
ds@1952
    70
	pstruct_t *p = firststruct;
ds@1952
    71
ds@1952
    72
	while (p)
ds@1952
    73
	{
ds@1952
    74
		if (strcmp(p->name, name) == 0)
ds@1952
    75
		{
ds@1952
    76
			return p;
ds@1952
    77
		}
ds@1952
    78
		p = p->next;
ds@1952
    79
	}
ds@1952
    80
ds@1952
    81
	return NULL;
ds@1952
    82
}
ds@1952
    83
ds@1952
    84
structarg_t *pstructs_addarg(pstruct_t *pstruct, const structarg_t *arg)
ds@1952
    85
{
ds@1952
    86
	structarg_t *newarg;
ds@1952
    87
	int i;
ds@1952
    88
ds@1952
    89
	for (i=0; i<pstruct->argcount; i++)
ds@1952
    90
	{
ds@1952
    91
		if (strcmp(pstruct->args[i]->name, arg->name) == 0)
ds@1952
    92
		{
ds@1952
    93
			/* Don't allow dup names */
ds@1952
    94
			return NULL;
ds@1952
    95
		}
ds@1952
    96
	}
ds@1952
    97
	
ds@1952
    98
	newarg = (structarg_t *)malloc(sizeof(structarg_t));
ds@1952
    99
ds@1952
   100
	memcpy(newarg, arg, sizeof(structarg_t));
ds@1952
   101
ds@1952
   102
	if (pstruct->argcount == 0)
ds@1952
   103
	{
ds@1952
   104
		pstruct->args = (structarg_t **)malloc(sizeof(structarg_t *) * 1);
ds@1952
   105
	} else {
ds@1952
   106
		pstruct->args = (structarg_t **)realloc(
ds@1952
   107
							pstruct->args,
ds@1952
   108
							sizeof(structarg_t *) * (pstruct->argcount + 1));
ds@1952
   109
	}
ds@1952
   110
ds@1952
   111
	newarg->offs = pstruct->argcount * sizeof(cell);
ds@1952
   112
	newarg->index = pstruct->argcount;
ds@1952
   113
	pstruct->args[pstruct->argcount++] = newarg;
ds@1952
   114
ds@1952
   115
	return newarg;
ds@1952
   116
}
ds@1952
   117
ds@1952
   118
void funcenums_free()
ds@1952
   119
{
ds@1952
   120
	funcenum_t *e, *next;
ds@1952
   121
ds@1952
   122
	e = firstenum;
ds@1952
   123
	while (e)
ds@1952
   124
	{
ds@1952
   125
		functag_t *tag, *nexttag;
ds@1952
   126
		tag = e->first;
ds@1952
   127
		while (tag)
ds@1952
   128
		{
ds@1952
   129
			nexttag = tag->next;
ds@1952
   130
			free(tag);
ds@1952
   131
			tag = nexttag;
ds@1952
   132
		}
ds@1952
   133
		next = e->next;
ds@1952
   134
		free(e);
ds@1952
   135
		e = next;
ds@1952
   136
	}
ds@1952
   137
ds@1952
   138
	firstenum = NULL;
ds@1952
   139
	lastenum = NULL;
ds@1952
   140
}
ds@1952
   141
ds@1952
   142
funcenum_t *funcenums_find_byval(int value)
ds@1952
   143
{
ds@1952
   144
	funcenum_t *e = firstenum;
ds@1952
   145
ds@1952
   146
	while (e)
ds@1952
   147
	{
ds@1952
   148
		if (e->value == value)
ds@1952
   149
		{
ds@1952
   150
			return e;
ds@1952
   151
		}
ds@1952
   152
		e = e->next;
ds@1952
   153
	}
ds@1952
   154
ds@1952
   155
	return NULL;
ds@1952
   156
}
ds@1952
   157
ds@1952
   158
funcenum_t *funcenums_add(const char *name)
ds@1952
   159
{
ds@1952
   160
	funcenum_t *e = (funcenum_t *)malloc(sizeof(funcenum_t));
ds@1952
   161
ds@1952
   162
	memset(e, 0, sizeof(funcenum_t));
ds@1952
   163
ds@1952
   164
	if (firstenum == NULL)
ds@1952
   165
	{
ds@1952
   166
		firstenum = e;
ds@1952
   167
		lastenum = e;
ds@1952
   168
	} else {
ds@1952
   169
		lastenum->next = e;
ds@1952
   170
		lastenum = e;
ds@1952
   171
	}
ds@1952
   172
ds@1952
   173
	strcpy(e->name, name);
ds@1952
   174
	e->value = pc_addfunctag((char *)name);
ds@1952
   175
ds@1952
   176
	return e;
ds@1952
   177
}
ds@1952
   178
ds@1952
   179
functag_t *functags_add(funcenum_t *en, functag_t *src)
ds@1952
   180
{
ds@1952
   181
	functag_t *t = (functag_t *)malloc(sizeof(functag_t));
ds@1952
   182
	
ds@1952
   183
	memcpy(t, src, sizeof(functag_t));
ds@1952
   184
ds@1952
   185
	t->next = NULL;
ds@1952
   186
ds@1952
   187
	if (en->first == NULL)
ds@1952
   188
	{
ds@1952
   189
		en->first = t;
ds@1952
   190
		en->last = t;
ds@1952
   191
	} else {
ds@1952
   192
		en->last->next = t;
ds@1952
   193
		en->last = t;
ds@1952
   194
	}
ds@1952
   195
ds@1952
   196
	return t;
ds@1952
   197
}
ds@1952
   198
ds@1952
   199
/**
ds@1952
   200
 * Creates a new mem usage tracker entry
ds@1952
   201
 */
ds@1952
   202
void _push_memlist(memuse_list_t **head)
ds@1952
   203
{
ds@1952
   204
  memuse_list_t *newlist = (memuse_list_t *)malloc(sizeof(memuse_list_t));
ds@1952
   205
  if (*head != NULL)
ds@1952
   206
  {
ds@1952
   207
    newlist->list_id = (*head)->list_id + 1;
ds@1952
   208
  } else {
ds@1952
   209
    newlist->list_id = 0;
ds@1952
   210
  }
ds@1952
   211
  newlist->prev = *head;
ds@1952
   212
  newlist->head = NULL;
ds@1952
   213
  *head = newlist;
ds@1952
   214
}
ds@1952
   215
ds@1952
   216
/**
ds@1952
   217
 * Pops a heap list but does not free it.
ds@1952
   218
 */
ds@1952
   219
memuse_list_t *_pop_save_memlist(memuse_list_t **head)
ds@1952
   220
{
ds@1952
   221
  memuse_list_t *oldlist = *head;
ds@1952
   222
  *head = (*head)->prev;
ds@1952
   223
  return oldlist;
ds@1952
   224
}
ds@1952
   225
ds@1952
   226
/**
ds@1952
   227
 * Marks a memory usage on a memory list
ds@1952
   228
 */
ds@1952
   229
int _mark_memlist(memuse_list_t *head, int type, int size)
ds@1952
   230
{
ds@1952
   231
  memuse_t *use;
ds@1952
   232
  if (type==MEMUSE_STATIC && size==0)
ds@1952
   233
  {
ds@1952
   234
    return 0;
ds@1952
   235
  }
ds@1952
   236
  use=head->head;
ds@1952
   237
  if (use && (type==MEMUSE_STATIC) 
ds@1952
   238
      && (use->type == type))
ds@1952
   239
  {
ds@1952
   240
    use->size += size;
ds@1952
   241
  } else {
ds@1952
   242
    use=(memuse_t *)malloc(sizeof(memuse_t));
ds@1952
   243
    use->type=type;
ds@1952
   244
    use->size=size;
ds@1952
   245
    use->prev=head->head;
ds@1952
   246
    head->head=use;
ds@1952
   247
  }
ds@1952
   248
  return size;
ds@1952
   249
}
ds@1952
   250
ds@1952
   251
void _reset_memlist(memuse_list_t **head)
ds@1952
   252
{
ds@1952
   253
  memuse_list_t *curlist = *head;
ds@1952
   254
  memuse_list_t *tmplist;
ds@1952
   255
  while (curlist) {
ds@1952
   256
    memuse_t *curuse = curlist->head;
ds@1952
   257
    memuse_t *tmpuse;
ds@1952
   258
    while (curuse) {
ds@1952
   259
      tmpuse = curuse->prev;
ds@1952
   260
      free(curuse);
ds@1952
   261
      curuse = tmpuse;
ds@1952
   262
    }
ds@1952
   263
    tmplist = curlist->prev;
ds@1952
   264
    free(curlist);
ds@1952
   265
    curlist = tmplist;
ds@1952
   266
  }
ds@1952
   267
  *head = NULL;
ds@1952
   268
}
ds@1952
   269
ds@1952
   270
ds@1952
   271
/**
ds@1952
   272
 * Wrapper for pushing the heap list
ds@1952
   273
 */
ds@1952
   274
void pushheaplist()
ds@1952
   275
{
ds@1952
   276
  _push_memlist(&heapusage);
ds@1952
   277
}
ds@1952
   278
ds@1952
   279
/**
ds@1952
   280
 * Wrapper for popping and saving the heap list
ds@1952
   281
 */
ds@1952
   282
memuse_list_t *popsaveheaplist()
ds@1952
   283
{
ds@1952
   284
  return _pop_save_memlist(&heapusage);
ds@1952
   285
}
ds@1952
   286
ds@1952
   287
/**
ds@1952
   288
 * Wrapper for marking the heap
ds@1952
   289
 */
ds@1952
   290
int markheap(int type, int size)
ds@1952
   291
{
ds@1952
   292
  return _mark_memlist(heapusage, type, size);
ds@1952
   293
}
ds@1952
   294
ds@1952
   295
/**
ds@1952
   296
 * Wrapper for pushing the stack list
ds@1952
   297
 */
ds@1952
   298
void pushstacklist()
ds@1952
   299
{
ds@1952
   300
  _push_memlist(&stackusage);
ds@1952
   301
}
ds@1952
   302
ds@1952
   303
/**
ds@1952
   304
 * Wrapper for marking the stack
ds@1952
   305
 */
ds@1952
   306
int markstack(int type, int size)
ds@1952
   307
{
ds@1952
   308
  return _mark_memlist(stackusage, type, size);
ds@1952
   309
}
ds@1952
   310
ds@1952
   311
/**
ds@1952
   312
 * Generates code to free all heap allocations on a tracker
ds@1952
   313
 */
ds@1952
   314
void _heap_freeusage(memuse_list_t *heap, int dofree)
ds@1952
   315
{
ds@1952
   316
  memuse_t *cur=heap->head;
ds@1952
   317
  memuse_t *tmp;
ds@1952
   318
  while (cur)
ds@1952
   319
  {
ds@1952
   320
    if (cur->type == MEMUSE_STATIC)
ds@1952
   321
	{
ds@1952
   322
      modheap((-1)*cur->size*sizeof(cell));
ds@1952
   323
    } else {
ds@1952
   324
      modheap_i();
ds@1952
   325
    }
ds@1952
   326
    if (dofree)
ds@1952
   327
    {
ds@1952
   328
      tmp=cur->prev;
ds@1952
   329
      free(cur);
ds@1952
   330
      cur=tmp;
ds@1952
   331
    } else {
ds@1952
   332
      cur=cur->prev;
ds@1952
   333
    }
ds@1952
   334
  }
ds@1952
   335
  if (dofree)
ds@1952
   336
  {
ds@1952
   337
    heap->head=NULL;
ds@1952
   338
  }
ds@1952
   339
}
ds@1952
   340
ds@1952
   341
void _stack_genusage(memuse_list_t *stack, int dofree)
ds@1952
   342
{
ds@1952
   343
  memuse_t *cur = stack->head;
ds@1952
   344
  memuse_t *tmp;
ds@1952
   345
  while (cur)
ds@1952
   346
  {
ds@1952
   347
    if (cur->type == MEMUSE_DYNAMIC)
ds@1952
   348
	{
ds@1952
   349
      /* no idea yet */
ds@1952
   350
      assert(0);
ds@1952
   351
	} else {
ds@1952
   352
      modstk(cur->size * sizeof(cell));
ds@1952
   353
	}
ds@1952
   354
	if (dofree)
ds@1952
   355
	{
ds@1952
   356
      tmp = cur->prev;
ds@1952
   357
      free(cur);
ds@1952
   358
      cur = tmp;
ds@1952
   359
	} else {
ds@1952
   360
      cur = cur->prev;
ds@1952
   361
	}
ds@1952
   362
  }
ds@1952
   363
  if (dofree)
ds@1952
   364
  {
ds@1952
   365
    stack->head = NULL;
ds@1952
   366
  }
ds@1952
   367
}
ds@1952
   368
ds@1952
   369
/**
ds@1952
   370
 * Pops a heap list and frees it.
ds@1952
   371
 */
ds@1952
   372
void popheaplist()
ds@1952
   373
{
ds@1952
   374
  memuse_list_t *oldlist;
ds@1952
   375
  assert(heapusage!=NULL);
ds@1952
   376
ds@1952
   377
  _heap_freeusage(heapusage, 1);
ds@1952
   378
  assert(heapusage->head==NULL);
ds@1952
   379
ds@1952
   380
  oldlist=heapusage->prev;
ds@1952
   381
  free(heapusage);
ds@1952
   382
  heapusage=oldlist;
ds@1952
   383
}
ds@1952
   384
ds@1952
   385
void genstackfree(int stop_id)
ds@1952
   386
{
ds@1952
   387
  memuse_list_t *curlist = stackusage;
ds@1952
   388
  while (curlist && curlist->list_id > stop_id)
ds@1952
   389
  {
ds@1952
   390
    _stack_genusage(curlist, 0);
ds@1952
   391
    curlist = curlist->prev;
ds@1952
   392
  }
ds@1952
   393
}
ds@1952
   394
ds@1952
   395
void genheapfree(int stop_id)
ds@1952
   396
{
ds@1952
   397
  memuse_list_t *curlist = heapusage;
ds@1952
   398
  while (curlist && curlist->list_id > stop_id)
ds@1952
   399
  {
ds@1952
   400
    _heap_freeusage(curlist, 0);
ds@1952
   401
    curlist = curlist->prev;
ds@1952
   402
  }
ds@1952
   403
}
ds@1952
   404
ds@1952
   405
void popstacklist(int codegen)
ds@1952
   406
{
ds@1952
   407
  memuse_list_t *oldlist;
ds@1952
   408
  assert(stackusage != NULL);
ds@1952
   409
ds@1952
   410
  if (codegen)
ds@1952
   411
  {
ds@1952
   412
    _stack_genusage(stackusage, 1);
ds@1952
   413
    assert(stackusage->head==NULL);
ds@1952
   414
  }
ds@1952
   415
ds@1952
   416
  oldlist = stackusage->prev;
ds@1952
   417
  free(stackusage);
ds@1952
   418
  stackusage = oldlist;
ds@1952
   419
}
ds@1952
   420
ds@1952
   421
void resetstacklist()
ds@1952
   422
{
ds@1952
   423
  _reset_memlist(&stackusage);
ds@1952
   424
}
ds@1952
   425
ds@1952
   426
void resetheaplist()
ds@1952
   427
{
ds@1952
   428
  _reset_memlist(&heapusage);
ds@1952
   429
}