PageRenderTime 37ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/rpython/memory/test/test_gctypelayout.py

https://bitbucket.org/pypy/pypy/
Python | 123 lines | 105 code | 13 blank | 5 comment | 7 complexity | 3024f291dc67f58c57b19132582df861 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import py
  2. from rpython.memory.gctypelayout import TypeLayoutBuilder, GCData
  3. from rpython.memory.gctypelayout import offsets_to_gc_pointers
  4. from rpython.memory.gctypelayout import gc_pointers_inside
  5. from rpython.rtyper.lltypesystem import lltype, llmemory
  6. from rpython.rtyper import rclass
  7. from rpython.rtyper.rclass import IR_IMMUTABLE, IR_QUASIIMMUTABLE
  8. from rpython.rtyper.test.test_llinterp import get_interpreter
  9. from rpython.flowspace.model import Constant
  10. class FakeGC:
  11. object_minimal_size = 0
  12. def getname(T):
  13. try:
  14. return "field:" + T._name
  15. except:
  16. return "field:" + T.__name__
  17. S = lltype.Struct('S', ('s', lltype.Signed), ('char', lltype.Char))
  18. GC_S = lltype.GcStruct('GC_S', ('S', S))
  19. A = lltype.Array(S)
  20. GC_A = lltype.GcArray(S)
  21. S2 = lltype.Struct('SPTRS',
  22. *[(getname(TYPE), lltype.Ptr(TYPE)) for TYPE in (GC_S, GC_A)])
  23. GC_S2 = lltype.GcStruct('GC_S2', ('S2', S2))
  24. A2 = lltype.Array(S2)
  25. GC_A2 = lltype.GcArray(S2)
  26. l = [(getname(TYPE), lltype.Ptr(TYPE)) for TYPE in (GC_S, GC_A)]
  27. l.append(('vararray', A2))
  28. GC_S3 = lltype.GcStruct('GC_S3', *l)
  29. def test_struct():
  30. for T, c in [(GC_S, 0), (GC_S2, 2), (GC_A, 0), (GC_A2, 0), (GC_S3, 2)]:
  31. assert len(offsets_to_gc_pointers(T)) == c
  32. def test_layout_builder(lltype2vtable=None):
  33. # XXX a very minimal test
  34. layoutbuilder = TypeLayoutBuilder(FakeGC, lltype2vtable)
  35. for T1, T2 in [(GC_A, GC_S), (GC_A2, GC_S2), (GC_S3, GC_S2)]:
  36. tid1 = layoutbuilder.get_type_id(T1)
  37. tid2 = layoutbuilder.get_type_id(T2)
  38. gcdata = GCData(layoutbuilder.type_info_group)
  39. lst1 = gcdata.q_varsize_offsets_to_gcpointers_in_var_part(tid1)
  40. lst2 = gcdata.q_offsets_to_gc_pointers(tid2)
  41. assert len(lst1) == len(lst2)
  42. return layoutbuilder
  43. def test_layout_builder_with_vtable():
  44. from rpython.rtyper.lltypesystem.lloperation import llop
  45. vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True)
  46. layoutbuilder = test_layout_builder({GC_S: vtable})
  47. tid1 = layoutbuilder.get_type_id(GC_S)
  48. tid2 = layoutbuilder.get_type_id(GC_S2)
  49. tid3 = layoutbuilder.get_type_id(GC_S3)
  50. group = layoutbuilder.type_info_group
  51. vt = llop.get_next_group_member(rclass.CLASSTYPE, group._as_ptr(), tid1,
  52. layoutbuilder.size_of_fixed_type_info)
  53. assert vt == vtable
  54. for tid in [tid2, tid3]:
  55. py.test.raises((lltype.InvalidCast, AssertionError),
  56. llop.get_next_group_member,
  57. rclass.CLASSTYPE, group._as_ptr(), tid,
  58. layoutbuilder.size_of_fixed_type_info)
  59. def test_constfold():
  60. layoutbuilder = TypeLayoutBuilder(FakeGC)
  61. tid1 = layoutbuilder.get_type_id(GC_A)
  62. tid2 = layoutbuilder.get_type_id(GC_S3)
  63. class MockGC:
  64. def set_query_functions(self, is_varsize,
  65. has_gcptr_in_varsize,
  66. is_gcarrayofgcptr,
  67. *rest):
  68. self.is_varsize = is_varsize
  69. self.has_gcptr_in_varsize = has_gcptr_in_varsize
  70. self.is_gcarrayofgcptr = is_gcarrayofgcptr
  71. gc = MockGC()
  72. layoutbuilder.initialize_gc_query_function(gc)
  73. #
  74. def f():
  75. return (1 * gc.is_varsize(tid1) +
  76. 10 * gc.has_gcptr_in_varsize(tid1) +
  77. 100 * gc.is_gcarrayofgcptr(tid1) +
  78. 1000 * gc.is_varsize(tid2) +
  79. 10000 * gc.has_gcptr_in_varsize(tid2) +
  80. 100000 * gc.is_gcarrayofgcptr(tid2))
  81. interp, graph = get_interpreter(f, [], backendopt=True)
  82. assert interp.eval_graph(graph, []) == 11001
  83. assert graph.startblock.exits[0].args == [Constant(11001, lltype.Signed)]
  84. def test_gc_pointers_inside():
  85. from rpython.rtyper import rclass
  86. PT = lltype.Ptr(lltype.GcStruct('T'))
  87. S1 = lltype.GcStruct('S', ('x', PT), ('y', PT))
  88. S2 = lltype.GcStruct('S', ('x', PT), ('y', PT),
  89. hints={'immutable': True})
  90. accessor = rclass.FieldListAccessor()
  91. S3 = lltype.GcStruct('S', ('x', PT), ('y', PT),
  92. hints={'immutable_fields': accessor})
  93. accessor.initialize(S3, {'x': IR_IMMUTABLE, 'y': IR_QUASIIMMUTABLE})
  94. #
  95. s1 = lltype.malloc(S1)
  96. adr = llmemory.cast_ptr_to_adr(s1)
  97. lst = list(gc_pointers_inside(s1._obj, adr, mutable_only=True))
  98. expected = [adr + llmemory.offsetof(S1, 'x'),
  99. adr + llmemory.offsetof(S1, 'y')]
  100. assert lst == expected or lst == expected[::-1]
  101. #
  102. s2 = lltype.malloc(S2)
  103. adr = llmemory.cast_ptr_to_adr(s2)
  104. lst = list(gc_pointers_inside(s2._obj, adr, mutable_only=True))
  105. assert lst == []
  106. #
  107. s3 = lltype.malloc(S3)
  108. adr = llmemory.cast_ptr_to_adr(s3)
  109. lst = list(gc_pointers_inside(s3._obj, adr, mutable_only=True))
  110. assert lst == [adr + llmemory.offsetof(S3, 'y')]