Cell.h 3.7 KB

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