gengc.lua 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. -- $Id: testes/gengc.lua $
  2. -- See Copyright Notice in file all.lua
  3. print('testing generational garbage collection')
  4. local debug = require"debug"
  5. assert(collectgarbage("isrunning"))
  6. collectgarbage()
  7. local oldmode = collectgarbage("generational")
  8. -- ensure that table barrier evolves correctly
  9. do
  10. local U = {}
  11. -- full collection makes 'U' old
  12. collectgarbage()
  13. assert(not T or T.gcage(U) == "old")
  14. -- U refers to a new table, so it becomes 'touched1'
  15. U[1] = {x = {234}}
  16. assert(not T or (T.gcage(U) == "touched1" and T.gcage(U[1]) == "new"))
  17. -- both U and the table survive one more collection
  18. collectgarbage("step", 0)
  19. assert(not T or (T.gcage(U) == "touched2" and T.gcage(U[1]) == "survival"))
  20. -- both U and the table survive yet another collection
  21. -- now everything is old
  22. collectgarbage("step", 0)
  23. assert(not T or (T.gcage(U) == "old" and T.gcage(U[1]) == "old1"))
  24. -- data was not corrupted
  25. assert(U[1].x[1] == 234)
  26. end
  27. do -- bug in 5.4.0
  28. -- When an object aged OLD1 is finalized, it is moved from the list
  29. -- 'finobj' to the *beginning* of the list 'allgc', but that part of the
  30. -- list was not being visited by 'markold'.
  31. local A = {}
  32. A[1] = false -- old anchor for object
  33. -- obj finalizer
  34. local function gcf (obj)
  35. A[1] = obj -- anchor object
  36. assert(not T or T.gcage(obj) == "old1")
  37. obj = nil -- remove it from the stack
  38. collectgarbage("step", 0) -- do a young collection
  39. print(getmetatable(A[1]).x) -- metatable was collected
  40. end
  41. collectgarbage() -- make A old
  42. local obj = {} -- create a new object
  43. collectgarbage("step", 0) -- make it a survival
  44. assert(not T or T.gcage(obj) == "survival")
  45. setmetatable(obj, {__gc = gcf, x = "ok"}) -- create its metatable
  46. assert(not T or T.gcage(getmetatable(obj)) == "new")
  47. obj = nil -- clear object
  48. collectgarbage("step", 0) -- will call obj's finalizer
  49. end
  50. if T == nil then
  51. (Message or print)('\n >>> testC not active: \z
  52. skipping some generational tests <<<\n')
  53. print 'OK'
  54. return
  55. end
  56. -- ensure that userdata barrier evolves correctly
  57. do
  58. local U = T.newuserdata(0, 1)
  59. -- full collection makes 'U' old
  60. collectgarbage()
  61. assert(T.gcage(U) == "old")
  62. -- U refers to a new table, so it becomes 'touched1'
  63. debug.setuservalue(U, {x = {234}})
  64. assert(T.gcage(U) == "touched1" and
  65. T.gcage(debug.getuservalue(U)) == "new")
  66. -- both U and the table survive one more collection
  67. collectgarbage("step", 0)
  68. assert(T.gcage(U) == "touched2" and
  69. T.gcage(debug.getuservalue(U)) == "survival")
  70. -- both U and the table survive yet another collection
  71. -- now everything is old
  72. collectgarbage("step", 0)
  73. assert(T.gcage(U) == "old" and
  74. T.gcage(debug.getuservalue(U)) == "old1")
  75. -- data was not corrupted
  76. assert(debug.getuservalue(U).x[1] == 234)
  77. end
  78. -- just to make sure
  79. assert(collectgarbage'isrunning')
  80. -- just to make sure
  81. assert(collectgarbage'isrunning')
  82. collectgarbage(oldmode)
  83. print('OK')