LCOV - code coverage report
Current view: top level - js/public - TraceKind.h (source / functions) Hit Total Coverage
Test: output.info Lines: 3 8 37.5 %
Date: 2017-07-14 16:53:18 Functions: 2 7 28.6 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
       7             : #ifndef js_TraceKind_h
       8             : #define js_TraceKind_h
       9             : 
      10             : #include "mozilla/UniquePtr.h"
      11             : 
      12             : #include "js/TypeDecls.h"
      13             : 
      14             : // Forward declarations of all the types a TraceKind can denote.
      15             : namespace js {
      16             : class BaseShape;
      17             : class LazyScript;
      18             : class ObjectGroup;
      19             : class RegExpShared;
      20             : class Shape;
      21             : class Scope;
      22             : namespace jit {
      23             : class JitCode;
      24             : } // namespace jit
      25             : } // namespace js
      26             : 
      27             : namespace JS {
      28             : 
      29             : // When tracing a thing, the GC needs to know about the layout of the object it
      30             : // is looking at. There are a fixed number of different layouts that the GC
      31             : // knows about. The "trace kind" is a static map which tells which layout a GC
      32             : // thing has.
      33             : //
      34             : // Although this map is public, the details are completely hidden. Not all of
      35             : // the matching C++ types are exposed, and those that are, are opaque.
      36             : //
      37             : // See Value::gcKind() and JSTraceCallback in Tracer.h for more details.
      38             : enum class TraceKind
      39             : {
      40             :     // These trace kinds have a publicly exposed, although opaque, C++ type.
      41             :     // Note: The order here is determined by our Value packing. Other users
      42             :     //       should sort alphabetically, for consistency.
      43             :     Object = 0x00,
      44             :     String = 0x02,
      45             :     Symbol = 0x03,
      46             : 
      47             :     // 0x1 is not used for any GCThing Value tag, so we use it for Script.
      48             :     Script = 0x01,
      49             : 
      50             :     // Shape details are exposed through JS_TraceShapeCycleCollectorChildren.
      51             :     Shape = 0x04,
      52             : 
      53             :     // ObjectGroup details are exposed through JS_TraceObjectGroupCycleCollectorChildren.
      54             :     ObjectGroup = 0x05,
      55             : 
      56             :     // The kind associated with a nullptr.
      57             :     Null = 0x06,
      58             : 
      59             :     // The following kinds do not have an exposed C++ idiom.
      60             :     BaseShape = 0x0F,
      61             :     JitCode = 0x1F,
      62             :     LazyScript = 0x2F,
      63             :     Scope = 0x3F,
      64             :     RegExpShared = 0x4F
      65             : };
      66             : const static uintptr_t OutOfLineTraceKindMask = 0x07;
      67             : static_assert(uintptr_t(JS::TraceKind::BaseShape) & OutOfLineTraceKindMask, "mask bits are set");
      68             : static_assert(uintptr_t(JS::TraceKind::JitCode) & OutOfLineTraceKindMask, "mask bits are set");
      69             : static_assert(uintptr_t(JS::TraceKind::LazyScript) & OutOfLineTraceKindMask, "mask bits are set");
      70             : static_assert(uintptr_t(JS::TraceKind::Scope) & OutOfLineTraceKindMask, "mask bits are set");
      71             : static_assert(uintptr_t(JS::TraceKind::RegExpShared) & OutOfLineTraceKindMask, "mask bits are set");
      72             : 
      73             : // When this header is imported inside SpiderMonkey, the class definitions are
      74             : // available and we can query those definitions to find the correct kind
      75             : // directly from the class hierarchy.
      76             : template <typename T>
      77             : struct MapTypeToTraceKind {
      78             :     static const JS::TraceKind kind = T::TraceKind;
      79             : };
      80             : 
      81             : // When this header is used outside SpiderMonkey, the class definitions are not
      82             : // available, so the following table containing all public GC types is used.
      83             : #define JS_FOR_EACH_TRACEKIND(D) \
      84             :  /* PrettyName       TypeName           AddToCCKind */ \
      85             :     D(BaseShape,     js::BaseShape,     true) \
      86             :     D(JitCode,       js::jit::JitCode,  true) \
      87             :     D(LazyScript,    js::LazyScript,    true) \
      88             :     D(Scope,         js::Scope,         true) \
      89             :     D(Object,        JSObject,          true) \
      90             :     D(ObjectGroup,   js::ObjectGroup,   true) \
      91             :     D(Script,        JSScript,          true) \
      92             :     D(Shape,         js::Shape,         true) \
      93             :     D(String,        JSString,          false) \
      94             :     D(Symbol,        JS::Symbol,        false) \
      95             :     D(RegExpShared,  js::RegExpShared,  true)
      96             : 
      97             : // Map from all public types to their trace kind.
      98             : #define JS_EXPAND_DEF(name, type, _) \
      99             :     template <> struct MapTypeToTraceKind<type> { \
     100             :         static const JS::TraceKind kind = JS::TraceKind::name; \
     101             :     };
     102             : JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
     103             : #undef JS_EXPAND_DEF
     104             : 
     105             : // RootKind is closely related to TraceKind. Whereas TraceKind's indices are
     106             : // laid out for convenient embedding as a pointer tag, the indicies of RootKind
     107             : // are designed for use as array keys via EnumeratedArray.
     108             : enum class RootKind : int8_t
     109             : {
     110             :     // These map 1:1 with trace kinds.
     111             : #define EXPAND_ROOT_KIND(name, _0, _1) \
     112             :     name,
     113             : JS_FOR_EACH_TRACEKIND(EXPAND_ROOT_KIND)
     114             : #undef EXPAND_ROOT_KIND
     115             : 
     116             :     // These tagged pointers are special-cased for performance.
     117             :     Id,
     118             :     Value,
     119             : 
     120             :     // Everything else.
     121             :     Traceable,
     122             : 
     123             :     Limit
     124             : };
     125             : 
     126             : // Most RootKind correspond directly to a trace kind.
     127             : template <TraceKind traceKind> struct MapTraceKindToRootKind {};
     128             : #define JS_EXPAND_DEF(name, _0, _1) \
     129             :     template <> struct MapTraceKindToRootKind<JS::TraceKind::name> { \
     130             :         static const JS::RootKind kind = JS::RootKind::name; \
     131             :     };
     132             : JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF)
     133             : #undef JS_EXPAND_DEF
     134             : 
     135             : // Specify the RootKind for all types. Value and jsid map to special cases;
     136             : // pointer types we can derive directly from the TraceKind; everything else
     137             : // should go in the Traceable list and use GCPolicy<T>::trace for tracing.
     138             : template <typename T>
     139             : struct MapTypeToRootKind {
     140             :     static const JS::RootKind kind = JS::RootKind::Traceable;
     141             : };
     142             : template <typename T>
     143             : struct MapTypeToRootKind<T*> {
     144             :     static const JS::RootKind kind =
     145             :         JS::MapTraceKindToRootKind<JS::MapTypeToTraceKind<T>::kind>::kind;
     146             : };
     147             : template <typename T>
     148             : struct MapTypeToRootKind<mozilla::UniquePtr<T>> {
     149             :     static const JS::RootKind kind = JS::MapTypeToRootKind<T>::kind;
     150             : };
     151             : template <> struct MapTypeToRootKind<JS::Value> {
     152             :     static const JS::RootKind kind = JS::RootKind::Value;
     153             : };
     154             : template <> struct MapTypeToRootKind<jsid> {
     155             :     static const JS::RootKind kind = JS::RootKind::Id;
     156             : };
     157             : template <> struct MapTypeToRootKind<JSFunction*> : public MapTypeToRootKind<JSObject*> {};
     158             : 
     159             : // Fortunately, few places in the system need to deal with fully abstract
     160             : // cells. In those places that do, we generally want to move to a layout
     161             : // templated function as soon as possible. This template wraps the upcast
     162             : // for that dispatch.
     163             : //
     164             : // Given a call:
     165             : //
     166             : //    DispatchTraceKindTyped(f, thing, traceKind, ... args)
     167             : //
     168             : // Downcast the |void *thing| to the specific type designated by |traceKind|,
     169             : // and pass it to the functor |f| along with |... args|, forwarded. Pass the
     170             : // type designated by |traceKind| as the functor's template argument. The
     171             : // |thing| parameter is optional; without it, we simply pass through |... args|.
     172             : 
     173             : // VS2017+, GCC and Clang require an explicit template declaration in front of
     174             : // the specialization of operator() because it is a dependent template. VS2015,
     175             : // on the other hand, gets very confused if we have a |template| token there.
     176             : // The clang-cl front end defines _MSC_VER, but still requires the explicit
     177             : // template declaration, so we must test for __clang__ here as well.
     178             : #if (defined(_MSC_VER) && _MSC_VER < 1910) && !defined(__clang__)
     179             : # define JS_DEPENDENT_TEMPLATE_HINT
     180             : #else
     181             : # define JS_DEPENDENT_TEMPLATE_HINT template
     182             : #endif
     183             : template <typename F, typename... Args>
     184             : auto
     185       20743 : DispatchTraceKindTyped(F f, JS::TraceKind traceKind, Args&&... args)
     186             :   -> decltype(f. JS_DEPENDENT_TEMPLATE_HINT operator()<JSObject>(mozilla::Forward<Args>(args)...))
     187             : {
     188       20743 :     switch (traceKind) {
     189             : #define JS_EXPAND_DEF(name, type, _) \
     190             :       case JS::TraceKind::name: \
     191             :         return f. JS_DEPENDENT_TEMPLATE_HINT operator()<type>(mozilla::Forward<Args>(args)...);
     192         497 :       JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
     193             : #undef JS_EXPAND_DEF
     194             :       default:
     195           0 :           MOZ_CRASH("Invalid trace kind in DispatchTraceKindTyped.");
     196             :     }
     197             : }
     198             : #undef JS_DEPENDENT_TEMPLATE_HINT
     199             : 
     200             : template <typename F, typename... Args>
     201             : auto
     202           0 : DispatchTraceKindTyped(F f, void* thing, JS::TraceKind traceKind, Args&&... args)
     203             :   -> decltype(f(static_cast<JSObject*>(nullptr), mozilla::Forward<Args>(args)...))
     204             : {
     205           0 :     switch (traceKind) {
     206             : #define JS_EXPAND_DEF(name, type, _) \
     207             :       case JS::TraceKind::name: \
     208             :           return f(static_cast<type*>(thing), mozilla::Forward<Args>(args)...);
     209           0 :       JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
     210             : #undef JS_EXPAND_DEF
     211             :       default:
     212           0 :           MOZ_CRASH("Invalid trace kind in DispatchTraceKindTyped.");
     213             :     }
     214             : }
     215             : 
     216             : } // namespace JS
     217             : 
     218             : #endif // js_TraceKind_h

Generated by: LCOV version 1.13