hash.c 6.4 KB

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