hash.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /*
  2. ** hash.c
  3. ** hash manager for lua
  4. */
  5. char *rcs_hash="$Id: hash.c,v 2.30 1996/05/06 14:30:27 roberto Exp roberto $";
  6. #include "mem.h"
  7. #include "opcode.h"
  8. #include "hash.h"
  9. #include "table.h"
  10. #include "lua.h"
  11. #define nhash(t) ((t)->nhash)
  12. #define nuse(t) ((t)->nuse)
  13. #define markarray(t) ((t)->mark)
  14. #define nodevector(t) ((t)->node)
  15. #define node(t,i) (&(t)->node[i])
  16. #define ref(n) (&(n)->ref)
  17. #define val(n) (&(n)->val)
  18. #define REHASH_LIMIT 0.70 /* avoid more than this % full */
  19. static Hash *listhead = NULL;
  20. /* hash dimensions values */
  21. static Long dimensions[] =
  22. {3L, 5L, 7L, 11L, 23L, 47L, 97L, 197L, 397L, 797L, 1597L, 3203L, 6421L,
  23. 12853L, 25717L, 51437L, 102811L, 205619L, 411233L, 822433L,
  24. 1644817L, 3289613L, 6579211L, 13158023L, MAX_INT};
  25. int luaI_redimension (int nhash)
  26. {
  27. int i;
  28. for (i=0; dimensions[i]<MAX_INT; i++)
  29. {
  30. if (dimensions[i] > nhash)
  31. return dimensions[i];
  32. }
  33. lua_error("table overflow");
  34. return 0; /* to avoid warnings */
  35. }
  36. static int hashindex (Hash *t, Object *ref) /* hash function */
  37. {
  38. switch (tag(ref))
  39. {
  40. case LUA_T_NIL:
  41. lua_error ("unexpected type to index table");
  42. return -1; /* UNREACHEABLE */
  43. case LUA_T_NUMBER:
  44. return (((int)nvalue(ref))%nhash(t));
  45. case LUA_T_STRING:
  46. return (int)((tsvalue(ref)->hash)%nhash(t)); /* make it a valid index */
  47. case LUA_T_FUNCTION:
  48. return (((IntPoint)ref->value.tf)%nhash(t));
  49. case LUA_T_CFUNCTION:
  50. return (((IntPoint)fvalue(ref))%nhash(t));
  51. case LUA_T_ARRAY:
  52. return (((IntPoint)avalue(ref))%nhash(t));
  53. default: /* user data */
  54. return (((IntPoint)uvalue(ref))%nhash(t));
  55. }
  56. }
  57. int lua_equalObj (Object *t1, Object *t2)
  58. {
  59. if (tag(t1) != tag(t2)) return 0;
  60. switch (tag(t1))
  61. {
  62. case LUA_T_NIL: return 1;
  63. case LUA_T_NUMBER: return nvalue(t1) == nvalue(t2);
  64. case LUA_T_STRING: return svalue(t1) == svalue(t2);
  65. case LUA_T_ARRAY: return avalue(t1) == avalue(t2);
  66. case LUA_T_FUNCTION: return t1->value.tf == t2->value.tf;
  67. case LUA_T_CFUNCTION: return fvalue(t1) == fvalue(t2);
  68. default: return uvalue(t1) == uvalue(t2);
  69. }
  70. }
  71. static int present (Hash *t, Object *ref)
  72. {
  73. int h = hashindex(t, ref);
  74. while (tag(ref(node(t, h))) != LUA_T_NIL)
  75. {
  76. if (lua_equalObj(ref, ref(node(t, h))))
  77. return h;
  78. h = (h+1) % nhash(t);
  79. }
  80. return h;
  81. }
  82. /*
  83. ** Alloc a vector node
  84. */
  85. static Node *hashnodecreate (int nhash)
  86. {
  87. int i;
  88. Node *v = newvector (nhash, Node);
  89. for (i=0; i<nhash; i++)
  90. tag(ref(&v[i])) = LUA_T_NIL;
  91. return v;
  92. }
  93. /*
  94. ** Create a new hash. Return the hash pointer or NULL on error.
  95. */
  96. static Hash *hashcreate (int nhash)
  97. {
  98. Hash *t = new(Hash);
  99. nhash = luaI_redimension((int)((float)nhash/REHASH_LIMIT));
  100. nodevector(t) = hashnodecreate(nhash);
  101. nhash(t) = nhash;
  102. nuse(t) = 0;
  103. markarray(t) = 0;
  104. return t;
  105. }
  106. /*
  107. ** Delete a hash
  108. */
  109. static void hashdelete (Hash *t)
  110. {
  111. luaI_free (nodevector(t));
  112. luaI_free(t);
  113. }
  114. /*
  115. ** Mark a hash and check its elements
  116. */
  117. void lua_hashmark (Hash *h)
  118. {
  119. if (markarray(h) == 0)
  120. {
  121. int i;
  122. markarray(h) = 1;
  123. for (i=0; i<nhash(h); i++)
  124. {
  125. Node *n = node(h,i);
  126. if (tag(ref(n)) != LUA_T_NIL)
  127. {
  128. lua_markobject(&n->ref);
  129. lua_markobject(&n->val);
  130. }
  131. }
  132. }
  133. }
  134. static void call_fallbacks (void)
  135. {
  136. Hash *curr_array;
  137. Object t;
  138. tag(&t) = LUA_T_ARRAY;
  139. for (curr_array = listhead; curr_array; curr_array = curr_array->next)
  140. if (markarray(curr_array) != 1)
  141. {
  142. avalue(&t) = curr_array;
  143. luaI_gcFB(&t);
  144. }
  145. tag(&t) = LUA_T_NIL;
  146. luaI_gcFB(&t); /* end of list */
  147. }
  148. /*
  149. ** Garbage collection to arrays
  150. ** Delete all unmarked arrays.
  151. */
  152. Long lua_hashcollector (void)
  153. {
  154. Hash *curr_array = listhead, *prev = NULL;
  155. Long counter = 0;
  156. call_fallbacks();
  157. while (curr_array != NULL)
  158. {
  159. Hash *next = curr_array->next;
  160. if (markarray(curr_array) != 1)
  161. {
  162. if (prev == NULL) listhead = next;
  163. else prev->next = next;
  164. hashdelete(curr_array);
  165. ++counter;
  166. }
  167. else
  168. {
  169. markarray(curr_array) = 0;
  170. prev = curr_array;
  171. }
  172. curr_array = next;
  173. }
  174. return counter;
  175. }
  176. /*
  177. ** Create a new array
  178. ** This function inserts the new array in the array list. It also
  179. ** executes garbage collection if the number of arrays created
  180. ** exceed a pre-defined range.
  181. */
  182. Hash *lua_createarray (int nhash)
  183. {
  184. Hash *array;
  185. lua_pack();
  186. array = hashcreate(nhash);
  187. array->next = listhead;
  188. listhead = array;
  189. return array;
  190. }
  191. /*
  192. ** Re-hash
  193. */
  194. static void rehash (Hash *t)
  195. {
  196. int i;
  197. int nold = nhash(t);
  198. Node *vold = nodevector(t);
  199. nhash(t) = luaI_redimension(nhash(t));
  200. nodevector(t) = hashnodecreate(nhash(t));
  201. for (i=0; i<nold; i++)
  202. {
  203. Node *n = vold+i;
  204. if (tag(ref(n)) != LUA_T_NIL && tag(val(n)) != LUA_T_NIL)
  205. *node(t, present(t, ref(n))) = *n; /* copy old node to new hahs */
  206. }
  207. luaI_free(vold);
  208. }
  209. /*
  210. ** If the hash node is present, return its pointer, otherwise return
  211. ** null.
  212. */
  213. Object *lua_hashget (Hash *t, Object *ref)
  214. {
  215. int h = present(t, ref);
  216. if (tag(ref(node(t, h))) != LUA_T_NIL) return val(node(t, h));
  217. else return NULL;
  218. }
  219. /*
  220. ** If the hash node is present, return its pointer, otherwise create a new
  221. ** node for the given reference and also return its pointer.
  222. */
  223. Object *lua_hashdefine (Hash *t, Object *ref)
  224. {
  225. int h;
  226. Node *n;
  227. h = present(t, ref);
  228. n = node(t, h);
  229. if (tag(ref(n)) == LUA_T_NIL)
  230. {
  231. nuse(t)++;
  232. if ((float)nuse(t) > (float)nhash(t)*REHASH_LIMIT)
  233. {
  234. rehash(t);
  235. h = present(t, ref);
  236. n = node(t, h);
  237. }
  238. *ref(n) = *ref;
  239. tag(val(n)) = LUA_T_NIL;
  240. }
  241. return (val(n));
  242. }
  243. /*
  244. ** Internal function to manipulate arrays.
  245. ** Given an array object and a reference value, return the next element
  246. ** in the hash.
  247. ** This function pushs the element value and its reference to the stack.
  248. */
  249. static void hashnext (Hash *t, int i)
  250. {
  251. if (i >= nhash(t))
  252. return;
  253. while (tag(ref(node(t,i))) == LUA_T_NIL || tag(val(node(t,i))) == LUA_T_NIL)
  254. {
  255. if (++i >= nhash(t))
  256. return;
  257. }
  258. luaI_pushobject(ref(node(t,i)));
  259. luaI_pushobject(val(node(t,i)));
  260. }
  261. void lua_next (void)
  262. {
  263. Hash *t;
  264. lua_Object o = lua_getparam(1);
  265. lua_Object r = lua_getparam(2);
  266. if (o == LUA_NOOBJECT || r == LUA_NOOBJECT)
  267. lua_error ("too few arguments to function `next'");
  268. if (lua_getparam(3) != LUA_NOOBJECT)
  269. lua_error ("too many arguments to function `next'");
  270. if (!lua_istable(o))
  271. lua_error ("first argument of function `next' is not a table");
  272. t = avalue(luaI_Address(o));
  273. if (lua_isnil(r))
  274. {
  275. hashnext(t, 0);
  276. }
  277. else
  278. {
  279. int h = present (t, luaI_Address(r));
  280. hashnext(t, h+1);
  281. }
  282. }