lref.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*
  2. ** $Id: lref.c,v 1.17 2000/08/09 19:16:57 roberto Exp roberto $
  3. ** reference mechanism
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include "lua.h"
  7. #include "lapi.h"
  8. #include "ldo.h"
  9. #include "lmem.h"
  10. #include "lref.h"
  11. #include "lstate.h"
  12. int lua_ref (lua_State *L, int lock) {
  13. int ref;
  14. luaA_checkCargs(L, 1);
  15. if (ttype(L->top-1) == TAG_NIL)
  16. ref = LUA_REFNIL;
  17. else {
  18. if (L->refFree != NONEXT) { /* is there a free place? */
  19. ref = L->refFree;
  20. L->refFree = L->refArray[ref].st;
  21. }
  22. else { /* no more free places */
  23. luaM_growvector(L, L->refArray, L->refSize, 1, struct Ref,
  24. "reference table overflow", MAX_INT);
  25. ref = L->refSize++;
  26. }
  27. L->refArray[ref].o = *(L->top-1);
  28. L->refArray[ref].st = lock ? LOCK : HOLD;
  29. }
  30. L->top--;
  31. return ref;
  32. }
  33. void lua_unref (lua_State *L, int ref) {
  34. if (ref >= 0) {
  35. if (ref >= L->refSize || L->refArray[ref].st >= 0)
  36. lua_error(L, "Lua API error - "
  37. "invalid argument for function `lua_unref'");
  38. L->refArray[ref].st = L->refFree;
  39. L->refFree = ref;
  40. }
  41. }
  42. int lua_pushref (lua_State *L, int ref) {
  43. if (ref == LUA_REFNIL)
  44. ttype(L->top) = TAG_NIL;
  45. else if (0 <= ref && ref < L->refSize &&
  46. (L->refArray[ref].st == LOCK || L->refArray[ref].st == HOLD))
  47. *L->top = L->refArray[ref].o;
  48. else
  49. return 0;
  50. incr_top;
  51. return 1;
  52. }
  53. void lua_beginblock (lua_State *L) {
  54. luaM_growvector(L, L->Cblocks, L->numCblocks, 1, struct C_Lua_Stack,
  55. "too many nested blocks", L->stacksize);
  56. L->Cblocks[L->numCblocks] = L->Cstack;
  57. L->numCblocks++;
  58. }
  59. void lua_endblock (lua_State *L) {
  60. if (L->numCblocks <= 0)
  61. lua_error(L, "Lua API error - no block to end");
  62. --L->numCblocks;
  63. L->Cstack = L->Cblocks[L->numCblocks];
  64. L->top = L->Cstack.base;
  65. }
  66. static int hasmark (const TObject *o) {
  67. /* valid only for locked objects */
  68. switch (o->ttype) {
  69. case TAG_STRING: case TAG_USERDATA:
  70. return tsvalue(o)->marked;
  71. case TAG_TABLE:
  72. return ismarked(hvalue(o));
  73. case TAG_LCLOSURE: case TAG_CCLOSURE:
  74. return ismarked(clvalue(o)->mark);
  75. default: /* number */
  76. return 1;
  77. }
  78. }
  79. /* for internal debugging only; check if a link of free refs is valid */
  80. #define VALIDLINK(L, st,n) (NONEXT <= (st) && (st) < (n))
  81. void luaR_invalidaterefs (lua_State *L) {
  82. int n = L->refSize;
  83. int i;
  84. for (i=0; i<n; i++) {
  85. struct Ref *r = &L->refArray[i];
  86. if (r->st == HOLD && !hasmark(&r->o))
  87. r->st = COLLECTED;
  88. LUA_ASSERT((r->st == LOCK && hasmark(&r->o)) ||
  89. r->st == COLLECTED ||
  90. r->st == NONEXT ||
  91. (r->st < n && VALIDLINK(L, L->refArray[r->st].st, n)),
  92. "inconsistent ref table");
  93. }
  94. LUA_ASSERT(VALIDLINK(L, L->refFree, n), "inconsistent ref table");
  95. }