LCOV - code coverage report
Current view: top level - js/public - Id.h (source / functions) Hit Total Coverage
Test: output.info Lines: 47 67 70.1 %
Date: 2017-07-14 16:53:18 Functions: 20 28 71.4 %
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_Id_h
       8             : #define js_Id_h
       9             : 
      10             : // A jsid is an identifier for a property or method of an object which is
      11             : // either a 31-bit unsigned integer, interned string or symbol.
      12             : //
      13             : // Also, there is an additional jsid value, JSID_VOID, which does not occur in
      14             : // JS scripts but may be used to indicate the absence of a valid jsid.  A void
      15             : // jsid is not a valid id and only arises as an exceptional API return value,
      16             : // such as in JS_NextProperty. Embeddings must not pass JSID_VOID into JSAPI
      17             : // entry points expecting a jsid and do not need to handle JSID_VOID in hooks
      18             : // receiving a jsid except when explicitly noted in the API contract.
      19             : //
      20             : // A jsid is not implicitly convertible to or from a Value; JS_ValueToId or
      21             : // JS_IdToValue must be used instead.
      22             : 
      23             : #include "jstypes.h"
      24             : 
      25             : #include "js/HeapAPI.h"
      26             : #include "js/RootingAPI.h"
      27             : #include "js/TypeDecls.h"
      28             : #include "js/Utility.h"
      29             : 
      30             : struct jsid
      31             : {
      32             :     size_t asBits;
      33     9024800 :     bool operator==(const jsid& rhs) const { return asBits == rhs.asBits; }
      34       16322 :     bool operator!=(const jsid& rhs) const { return asBits != rhs.asBits; }
      35             : } JS_HAZ_GC_POINTER;
      36             : #define JSID_BITS(id) (id.asBits)
      37             : 
      38             : #define JSID_TYPE_STRING                 0x0
      39             : #define JSID_TYPE_INT                    0x1
      40             : #define JSID_TYPE_VOID                   0x2
      41             : #define JSID_TYPE_SYMBOL                 0x4
      42             : #define JSID_TYPE_MASK                   0x7
      43             : 
      44             : // Avoid using canonical 'id' for jsid parameters since this is a magic word in
      45             : // Objective-C++ which, apparently, wants to be able to #include jsapi.h.
      46             : #define id iden
      47             : 
      48             : static MOZ_ALWAYS_INLINE bool
      49     2026196 : JSID_IS_STRING(jsid id)
      50             : {
      51     2026196 :     return (JSID_BITS(id) & JSID_TYPE_MASK) == 0;
      52             : }
      53             : 
      54             : static MOZ_ALWAYS_INLINE JSString*
      55      886022 : JSID_TO_STRING(jsid id)
      56             : {
      57      886022 :     MOZ_ASSERT(JSID_IS_STRING(id));
      58      886022 :     return (JSString*)JSID_BITS(id);
      59             : }
      60             : 
      61             : /**
      62             :  * Only JSStrings that have been interned via the JSAPI can be turned into
      63             :  * jsids by API clients.
      64             :  *
      65             :  * N.B. if a jsid is backed by a string which has not been interned, that
      66             :  * string must be appropriately rooted to avoid being collected by the GC.
      67             :  */
      68             : JS_PUBLIC_API(jsid)
      69             : INTERNED_STRING_TO_JSID(JSContext* cx, JSString* str);
      70             : 
      71             : static MOZ_ALWAYS_INLINE bool
      72     1308981 : JSID_IS_INT(jsid id)
      73             : {
      74     1308981 :     return !!(JSID_BITS(id) & JSID_TYPE_INT);
      75             : }
      76             : 
      77             : static MOZ_ALWAYS_INLINE int32_t
      78       25158 : JSID_TO_INT(jsid id)
      79             : {
      80       25158 :     MOZ_ASSERT(JSID_IS_INT(id));
      81       25158 :     uint32_t bits = static_cast<uint32_t>(JSID_BITS(id)) >> 1;
      82       25158 :     return static_cast<int32_t>(bits);
      83             : }
      84             : 
      85             : #define JSID_INT_MIN  0
      86             : #define JSID_INT_MAX  INT32_MAX
      87             : 
      88             : static MOZ_ALWAYS_INLINE bool
      89       18558 : INT_FITS_IN_JSID(int32_t i)
      90             : {
      91       18558 :     return i >= 0;
      92             : }
      93             : 
      94             : static MOZ_ALWAYS_INLINE jsid
      95       17199 : INT_TO_JSID(int32_t i)
      96             : {
      97             :     jsid id;
      98       17199 :     MOZ_ASSERT(INT_FITS_IN_JSID(i));
      99       17199 :     uint32_t bits = (static_cast<uint32_t>(i) << 1) | JSID_TYPE_INT;
     100       17199 :     JSID_BITS(id) = static_cast<size_t>(bits);
     101       17199 :     return id;
     102             : }
     103             : 
     104             : static MOZ_ALWAYS_INLINE bool
     105      206829 : JSID_IS_SYMBOL(jsid id)
     106             : {
     107      251569 :     return (JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_SYMBOL &&
     108      251569 :            JSID_BITS(id) != JSID_TYPE_SYMBOL;
     109             : }
     110             : 
     111             : static MOZ_ALWAYS_INLINE JS::Symbol*
     112       19723 : JSID_TO_SYMBOL(jsid id)
     113             : {
     114       19723 :     MOZ_ASSERT(JSID_IS_SYMBOL(id));
     115       19723 :     return (JS::Symbol*)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK);
     116             : }
     117             : 
     118             : static MOZ_ALWAYS_INLINE jsid
     119       10422 : SYMBOL_TO_JSID(JS::Symbol* sym)
     120             : {
     121             :     jsid id;
     122       10422 :     MOZ_ASSERT(sym != nullptr);
     123       10422 :     MOZ_ASSERT((size_t(sym) & JSID_TYPE_MASK) == 0);
     124       10422 :     MOZ_ASSERT(!js::gc::IsInsideNursery(reinterpret_cast<js::gc::Cell*>(sym)));
     125       10422 :     JSID_BITS(id) = (size_t(sym) | JSID_TYPE_SYMBOL);
     126       10422 :     return id;
     127             : }
     128             : 
     129             : static MOZ_ALWAYS_INLINE bool
     130        5388 : JSID_IS_GCTHING(jsid id)
     131             : {
     132        5388 :     return JSID_IS_STRING(id) || JSID_IS_SYMBOL(id);
     133             : }
     134             : 
     135             : static MOZ_ALWAYS_INLINE JS::GCCellPtr
     136           0 : JSID_TO_GCTHING(jsid id)
     137             : {
     138           0 :     void* thing = (void*)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK);
     139           0 :     if (JSID_IS_STRING(id))
     140           0 :         return JS::GCCellPtr(thing, JS::TraceKind::String);
     141           0 :     MOZ_ASSERT(JSID_IS_SYMBOL(id));
     142           0 :     return JS::GCCellPtr(thing, JS::TraceKind::Symbol);
     143             : }
     144             : 
     145             : static MOZ_ALWAYS_INLINE bool
     146     8614149 : JSID_IS_VOID(const jsid id)
     147             : {
     148     8614149 :     MOZ_ASSERT_IF(((size_t)JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_VOID,
     149             :                  JSID_BITS(id) == JSID_TYPE_VOID);
     150     8614149 :     return (size_t)JSID_BITS(id) == JSID_TYPE_VOID;
     151             : }
     152             : 
     153             : static MOZ_ALWAYS_INLINE bool
     154    13288312 : JSID_IS_EMPTY(const jsid id)
     155             : {
     156    13288312 :     return (size_t)JSID_BITS(id) == JSID_TYPE_SYMBOL;
     157             : }
     158             : 
     159             : extern JS_PUBLIC_DATA(const jsid) JSID_VOID;
     160             : extern JS_PUBLIC_DATA(const jsid) JSID_EMPTY;
     161             : 
     162             : extern JS_PUBLIC_DATA(const JS::HandleId) JSID_VOIDHANDLE;
     163             : extern JS_PUBLIC_DATA(const JS::HandleId) JSID_EMPTYHANDLE;
     164             : 
     165             : namespace JS {
     166             : 
     167             : template <>
     168             : struct GCPolicy<jsid>
     169             : {
     170      186459 :     static jsid initial() { return JSID_VOID; }
     171           0 :     static void trace(JSTracer* trc, jsid* idp, const char* name) {
     172           0 :         js::UnsafeTraceManuallyBarrieredEdge(trc, idp, name);
     173           0 :     }
     174             : };
     175             : 
     176             : } // namespace JS
     177             : 
     178             : namespace js {
     179             : 
     180             : template <>
     181             : struct BarrierMethods<jsid>
     182             : {
     183           0 :     static gc::Cell* asGCThingOrNull(jsid id) {
     184           0 :         if (JSID_IS_STRING(id))
     185           0 :             return reinterpret_cast<gc::Cell*>(JSID_TO_STRING(id));
     186           0 :         if (JSID_IS_SYMBOL(id))
     187           0 :             return reinterpret_cast<gc::Cell*>(JSID_TO_SYMBOL(id));
     188           0 :         return nullptr;
     189             :     }
     190           0 :     static void postBarrier(jsid* idp, jsid prev, jsid next) {}
     191           0 :     static void exposeToJS(jsid id) {
     192           0 :         if (JSID_IS_GCTHING(id))
     193           0 :             js::gc::ExposeGCThingToActiveJS(JSID_TO_GCTHING(id));
     194           0 :     }
     195             : };
     196             : 
     197             : // If the jsid is a GC pointer type, convert to that type and call |f| with
     198             : // the pointer. If the jsid is not a GC type, calls F::defaultValue.
     199             : template <typename F, typename... Args>
     200             : auto
     201        6162 : DispatchTyped(F f, const jsid& id, Args&&... args)
     202             :   -> decltype(f(static_cast<JSString*>(nullptr), mozilla::Forward<Args>(args)...))
     203             : {
     204        6162 :     if (JSID_IS_STRING(id))
     205        4824 :         return f(JSID_TO_STRING(id), mozilla::Forward<Args>(args)...);
     206        1338 :     if (JSID_IS_SYMBOL(id))
     207          38 :         return f(JSID_TO_SYMBOL(id), mozilla::Forward<Args>(args)...);
     208        1300 :     MOZ_ASSERT(!JSID_IS_GCTHING(id));
     209        1300 :     return F::defaultValue(id);
     210             : }
     211             : 
     212             : #undef id
     213             : 
     214             : } // namespace js
     215             : 
     216             : #endif /* js_Id_h */

Generated by: LCOV version 1.13