GCPolicyAPI.h 5.4 KB

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