GCPolicyAPI.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2. * This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. // GC Policy Mechanism
  6. // A GCPolicy controls how the GC interacts with both direct pointers to GC
  7. // things (e.g. JSObject* or JSString*), tagged and/or optional pointers to GC
  8. // things (e.g. Value or jsid), and C++ container types (e.g.
  9. // JSPropertyDescriptor or GCHashMap).
  10. //
  11. // The GCPolicy provides at a minimum:
  12. //
  13. // static T initial()
  14. // - Construct and return an empty T.
  15. //
  16. // static void trace(JSTracer, T* tp, const char* name)
  17. // - Trace the edge |*tp|, calling the edge |name|. Containers like
  18. // GCHashMap and GCHashSet use this method to trace their children.
  19. //
  20. // static bool needsSweep(T* tp)
  21. // - Return true if |*tp| is about to be finalized. Otherwise, update the
  22. // edge for moving GC, and return false. Containers like GCHashMap and
  23. // GCHashSet use this method to decide when to remove an entry: if this
  24. // function returns true on a key/value/member/etc, its entry is dropped
  25. // from the container. Specializing this method is the standard way to
  26. // get custom weak behavior from a container type.
  27. //
  28. // The default GCPolicy<T> assumes that T has a default constructor and |trace|
  29. // and |needsSweep| methods, and forwards to them. GCPolicy has appropriate
  30. // specializations for pointers to GC things and pointer-like types like
  31. // JS::Heap<T> and mozilla::UniquePtr<T>.
  32. //
  33. // There are some stock structs your specializations can inherit from.
  34. // IgnoreGCPolicy<T> does nothing. StructGCPolicy<T> forwards the methods to the
  35. // referent type T.
  36. #ifndef GCPolicyAPI_h
  37. #define GCPolicyAPI_h
  38. #include "mozilla/UniquePtr.h"
  39. #include "js/TraceKind.h"
  40. #include "js/TracingAPI.h"
  41. // Expand the given macro D for each public GC pointer.
  42. #define FOR_EACH_PUBLIC_GC_POINTER_TYPE(D) \
  43. D(JS::Symbol*) \
  44. D(JSAtom*) \
  45. D(JSFunction*) \
  46. D(JSObject*) \
  47. D(JSScript*) \
  48. D(JSString*)
  49. // Expand the given macro D for each public tagged GC pointer type.
  50. #define FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(D) \
  51. D(JS::Value) \
  52. D(jsid)
  53. #define FOR_EACH_PUBLIC_AGGREGATE_GC_POINTER_TYPE(D) \
  54. D(JSPropertyDescriptor)
  55. class JSAtom;
  56. class JSFunction;
  57. class JSObject;
  58. class JSScript;
  59. class JSString;
  60. namespace JS {
  61. class Symbol;
  62. }
  63. namespace JS {
  64. // Defines a policy for container types with non-GC, i.e. C storage. This
  65. // policy dispatches to the underlying struct for GC interactions.
  66. template <typename T>
  67. struct StructGCPolicy
  68. {
  69. static T initial() {
  70. return T();
  71. }
  72. static void trace(JSTracer* trc, T* tp, const char* name) {
  73. tp->trace(trc);
  74. }
  75. static void sweep(T* tp) {
  76. return tp->sweep();
  77. }
  78. static bool needsSweep(T* tp) {
  79. return tp->needsSweep();
  80. }
  81. };
  82. // The default GC policy attempts to defer to methods on the underlying type.
  83. // Most C++ structures that contain a default constructor, a trace function and
  84. // a sweep function will work out of the box with Rooted, Handle, GCVector,
  85. // and GCHash{Set,Map}.
  86. template <typename T> struct GCPolicy : public StructGCPolicy<T> {};
  87. // This policy ignores any GC interaction, e.g. for non-GC types.
  88. template <typename T>
  89. struct IgnoreGCPolicy {
  90. static T initial() { return T(); }
  91. static void trace(JSTracer* trc, T* t, const char* name) {}
  92. static bool needsSweep(T* v) { return false; }
  93. };
  94. template <> struct GCPolicy<uint32_t> : public IgnoreGCPolicy<uint32_t> {};
  95. template <> struct GCPolicy<uint64_t> : public IgnoreGCPolicy<uint64_t> {};
  96. template <typename T>
  97. struct GCPointerPolicy
  98. {
  99. static T initial() { return nullptr; }
  100. static void trace(JSTracer* trc, T* vp, const char* name) {
  101. if (*vp)
  102. js::UnsafeTraceManuallyBarrieredEdge(trc, vp, name);
  103. }
  104. static bool needsSweep(T* vp) {
  105. if (*vp)
  106. return js::gc::IsAboutToBeFinalizedUnbarriered(vp);
  107. return false;
  108. }
  109. };
  110. template <> struct GCPolicy<JS::Symbol*> : public GCPointerPolicy<JS::Symbol*> {};
  111. template <> struct GCPolicy<JSAtom*> : public GCPointerPolicy<JSAtom*> {};
  112. template <> struct GCPolicy<JSFunction*> : public GCPointerPolicy<JSFunction*> {};
  113. template <> struct GCPolicy<JSObject*> : public GCPointerPolicy<JSObject*> {};
  114. template <> struct GCPolicy<JSScript*> : public GCPointerPolicy<JSScript*> {};
  115. template <> struct GCPolicy<JSString*> : public GCPointerPolicy<JSString*> {};
  116. template <typename T>
  117. struct GCPolicy<JS::Heap<T>>
  118. {
  119. static void trace(JSTracer* trc, JS::Heap<T>* thingp, const char* name) {
  120. TraceEdge(trc, thingp, name);
  121. }
  122. static bool needsSweep(JS::Heap<T>* thingp) {
  123. return js::gc::EdgeNeedsSweep(thingp);
  124. }
  125. };
  126. // GCPolicy<UniquePtr<T>> forwards the contained pointer to GCPolicy<T>.
  127. template <typename T, typename D>
  128. struct GCPolicy<mozilla::UniquePtr<T, D>>
  129. {
  130. static mozilla::UniquePtr<T,D> initial() { return mozilla::UniquePtr<T,D>(); }
  131. static void trace(JSTracer* trc, mozilla::UniquePtr<T,D>* tp, const char* name) {
  132. if (tp->get())
  133. GCPolicy<T>::trace(trc, tp->get(), name);
  134. }
  135. static bool needsSweep(mozilla::UniquePtr<T,D>* tp) {
  136. if (tp->get())
  137. return GCPolicy<T>::needsSweep(tp->get());
  138. return false;
  139. }
  140. };
  141. } // namespace JS
  142. #endif // GCPolicyAPI_h