Cell.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /*
  2. * Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Badge.h>
  8. #include <AK/Format.h>
  9. #include <AK/Forward.h>
  10. #include <AK/Noncopyable.h>
  11. #include <AK/StringView.h>
  12. #include <LibJS/Forward.h>
  13. #include <LibJS/Heap/GCPtr.h>
  14. #include <LibJS/Heap/Internals.h>
  15. namespace JS {
  16. #define JS_CELL(class_, base_class) \
  17. public: \
  18. using Base = base_class; \
  19. virtual StringView class_name() const override \
  20. { \
  21. return #class_##sv; \
  22. } \
  23. friend class JS::Heap;
  24. class Cell {
  25. AK_MAKE_NONCOPYABLE(Cell);
  26. AK_MAKE_NONMOVABLE(Cell);
  27. public:
  28. virtual void initialize(Realm&);
  29. virtual ~Cell() = default;
  30. bool is_marked() const { return m_mark; }
  31. void set_marked(bool b) { m_mark = b; }
  32. enum class State : bool {
  33. Live,
  34. Dead,
  35. };
  36. State state() const { return m_state; }
  37. void set_state(State state) { m_state = state; }
  38. virtual StringView class_name() const = 0;
  39. class Visitor {
  40. public:
  41. void visit(Cell* cell)
  42. {
  43. if (cell)
  44. visit_impl(*cell);
  45. }
  46. void visit(Cell& cell)
  47. {
  48. visit_impl(cell);
  49. }
  50. template<typename T>
  51. void visit(GCPtr<T> cell)
  52. {
  53. if (cell)
  54. visit_impl(const_cast<RemoveConst<T>&>(*cell.ptr()));
  55. }
  56. template<typename T>
  57. void visit(NonnullGCPtr<T> cell)
  58. {
  59. visit_impl(const_cast<RemoveConst<T>&>(*cell.ptr()));
  60. }
  61. void visit(Value value);
  62. // Allow explicitly ignoring a GC-allocated member in a visit_edges implementation instead
  63. // of just not using it.
  64. template<typename T>
  65. void ignore(T const&)
  66. {
  67. }
  68. virtual void visit_possible_values(ReadonlyBytes) = 0;
  69. protected:
  70. virtual void visit_impl(Cell&) = 0;
  71. virtual ~Visitor() = default;
  72. };
  73. virtual void visit_edges(Visitor&) { }
  74. // This will be called on unmarked objects by the garbage collector in a separate pass before destruction.
  75. virtual void finalize() { }
  76. // This allows cells to survive GC by choice, even if nothing points to them.
  77. // It's used to implement special rules in the web platform.
  78. // NOTE: Cells must call set_overrides_must_survive_garbage_collection() for this to be honored.
  79. virtual bool must_survive_garbage_collection() const { return false; }
  80. bool overrides_must_survive_garbage_collection(Badge<Heap>) const { return m_overrides_must_survive_garbage_collection; }
  81. ALWAYS_INLINE Heap& heap() const { return HeapBlockBase::from_cell(this)->heap(); }
  82. ALWAYS_INLINE VM& vm() const { return bit_cast<HeapBase*>(&heap())->vm(); }
  83. protected:
  84. Cell() = default;
  85. void set_overrides_must_survive_garbage_collection(bool b) { m_overrides_must_survive_garbage_collection = b; }
  86. private:
  87. bool m_mark : 1 { false };
  88. bool m_overrides_must_survive_garbage_collection : 1 { false };
  89. State m_state : 1 { State::Live };
  90. };
  91. }
  92. template<>
  93. struct AK::Formatter<JS::Cell> : AK::Formatter<FormatString> {
  94. ErrorOr<void> format(FormatBuilder& builder, JS::Cell const* cell)
  95. {
  96. if (!cell)
  97. return builder.put_string("Cell{nullptr}"sv);
  98. return Formatter<FormatString>::format(builder, "{}({})"sv, cell->class_name(), cell);
  99. }
  100. };