tree.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*
  2. ** tree.c
  3. ** TecCGraf - PUC-Rio
  4. */
  5. char *rcs_tree="$Id: tree.c,v 1.25 1997/05/05 20:21:23 roberto Exp roberto $";
  6. #include <string.h>
  7. #include "luamem.h"
  8. #include "lua.h"
  9. #include "tree.h"
  10. #include "lex.h"
  11. #include "hash.h"
  12. #include "table.h"
  13. #include "fallback.h"
  14. #define NUM_HASHS 64
  15. typedef struct {
  16. int size;
  17. int nuse; /* number of elements (including EMPTYs) */
  18. TaggedString **hash;
  19. } stringtable;
  20. static int initialized = 0;
  21. static stringtable string_root[NUM_HASHS];
  22. static TaggedString EMPTY = {LUA_T_STRING, NULL, 0, NOT_USED, NOT_USED,
  23. 0, 2, {0}};
  24. static unsigned long hash (char *buff, long size)
  25. {
  26. unsigned long h = 0;
  27. while (size--)
  28. h = ((h<<5)-h)^(unsigned char)*(buff++);
  29. return h;
  30. }
  31. static void luaI_inittree (void)
  32. {
  33. int i;
  34. for (i=0; i<NUM_HASHS; i++) {
  35. string_root[i].size = 0;
  36. string_root[i].nuse = 0;
  37. string_root[i].hash = NULL;
  38. }
  39. }
  40. static void initialize (void)
  41. {
  42. initialized = 1;
  43. luaI_inittree();
  44. luaI_addReserved();
  45. luaI_initsymbol();
  46. luaI_initconstant();
  47. luaI_initfallbacks();
  48. }
  49. static void grow (stringtable *tb)
  50. {
  51. int newsize = luaI_redimension(tb->size);
  52. TaggedString **newhash = newvector(newsize, TaggedString *);
  53. int i;
  54. for (i=0; i<newsize; i++)
  55. newhash[i] = NULL;
  56. /* rehash */
  57. tb->nuse = 0;
  58. for (i=0; i<tb->size; i++)
  59. if (tb->hash[i] != NULL && tb->hash[i] != &EMPTY) {
  60. int h = tb->hash[i]->hash%newsize;
  61. while (newhash[h])
  62. h = (h+1)%newsize;
  63. newhash[h] = tb->hash[i];
  64. tb->nuse++;
  65. }
  66. luaI_free(tb->hash);
  67. tb->size = newsize;
  68. tb->hash = newhash;
  69. }
  70. static TaggedString *insert (char *buff, long size, int tag, stringtable *tb)
  71. {
  72. TaggedString *ts;
  73. unsigned long h = hash(buff, size);
  74. int i;
  75. int j = -1;
  76. if ((Long)tb->nuse*3 >= (Long)tb->size*2)
  77. {
  78. if (!initialized)
  79. initialize();
  80. grow(tb);
  81. }
  82. i = h%tb->size;
  83. while ((ts = tb->hash[i]) != NULL)
  84. {
  85. if (ts == &EMPTY)
  86. j = i;
  87. else if (ts->size == size && ts->tag == tag &&
  88. memcmp(buff, ts->str, size) == 0)
  89. return ts;
  90. i = (i+1)%tb->size;
  91. }
  92. /* not found */
  93. lua_pack();
  94. if (j != -1) /* is there an EMPTY space? */
  95. i = j;
  96. else
  97. tb->nuse++;
  98. ts = tb->hash[i] = (TaggedString *)luaI_malloc(sizeof(TaggedString)+size-1);
  99. memcpy(ts->str, buff, size);
  100. ts->tag = tag;
  101. ts->size = size;
  102. ts->marked = 0;
  103. ts->hash = h;
  104. ts->varindex = ts->constindex = NOT_USED;
  105. return ts;
  106. }
  107. TaggedString *luaI_createuserdata (char *buff, long size, int tag)
  108. {
  109. return insert(buff, size, tag, &string_root[(unsigned)buff[0]%NUM_HASHS]);
  110. }
  111. TaggedString *lua_createstring (char *str)
  112. {
  113. return luaI_createuserdata(str, strlen(str)+1, LUA_T_STRING);
  114. }
  115. void luaI_strcallIM (TaggedString *l)
  116. {
  117. TObject o;
  118. ttype(&o) = LUA_T_USERDATA;
  119. for (; l; l=l->next) {
  120. tsvalue(&o) = l;
  121. luaI_gcIM(&o);
  122. }
  123. }
  124. void luaI_strfree (TaggedString *l)
  125. {
  126. while (l) {
  127. TaggedString *next = l->next;
  128. luaI_free(l);
  129. l = next;
  130. }
  131. }
  132. /*
  133. ** Garbage collection function.
  134. */
  135. TaggedString *luaI_strcollector (long *acum)
  136. {
  137. Long counter = 0;
  138. TaggedString *frees = NULL;
  139. int i;
  140. for (i=0; i<NUM_HASHS; i++)
  141. {
  142. stringtable *tb = &string_root[i];
  143. int j;
  144. for (j=0; j<tb->size; j++)
  145. {
  146. TaggedString *t = tb->hash[j];
  147. if (t != NULL && t->marked <= 1)
  148. {
  149. if (t->marked)
  150. t->marked = 0;
  151. else
  152. {
  153. t->next = frees;
  154. frees = t;
  155. tb->hash[j] = &EMPTY;
  156. counter++;
  157. }
  158. }
  159. }
  160. }
  161. *acum += counter;
  162. return frees;
  163. }