Bumping manifests a=b2g-bump
[gecko.git] / js / public / Id.h
blob692655b27a0dcacf5cb6f490eebd9cfcd25022e4
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/. */
7 #ifndef js_Id_h
8 #define js_Id_h
10 // A jsid is an identifier for a property or method of an object which is
11 // either a 31-bit signed integer, interned string or object.
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.
20 // A jsid is not implicitly convertible to or from a jsval; JS_ValueToId or
21 // JS_IdToValue must be used instead.
23 #include "jstypes.h"
25 #include "js/HeapAPI.h"
26 #include "js/RootingAPI.h"
27 #include "js/TypeDecls.h"
28 #include "js/Utility.h"
30 struct jsid
32 size_t asBits;
33 bool operator==(jsid rhs) const { return asBits == rhs.asBits; }
34 bool operator!=(jsid rhs) const { return asBits != rhs.asBits; }
36 #define JSID_BITS(id) (id.asBits)
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
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
48 static MOZ_ALWAYS_INLINE bool
49 JSID_IS_STRING(jsid id)
51 return (JSID_BITS(id) & JSID_TYPE_MASK) == 0;
54 static MOZ_ALWAYS_INLINE JSString*
55 JSID_TO_STRING(jsid id)
57 MOZ_ASSERT(JSID_IS_STRING(id));
58 return (JSString*)JSID_BITS(id);
62 * Only JSStrings that have been interned via the JSAPI can be turned into
63 * jsids by API clients.
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.
68 JS_PUBLIC_API(jsid)
69 INTERNED_STRING_TO_JSID(JSContext* cx, JSString* str);
71 static MOZ_ALWAYS_INLINE bool
72 JSID_IS_ZERO(jsid id)
74 return JSID_BITS(id) == 0;
77 static MOZ_ALWAYS_INLINE bool
78 JSID_IS_INT(jsid id)
80 return !!(JSID_BITS(id) & JSID_TYPE_INT);
83 static MOZ_ALWAYS_INLINE int32_t
84 JSID_TO_INT(jsid id)
86 MOZ_ASSERT(JSID_IS_INT(id));
87 return ((uint32_t)JSID_BITS(id)) >> 1;
90 #define JSID_INT_MIN 0
91 #define JSID_INT_MAX INT32_MAX
93 static MOZ_ALWAYS_INLINE bool
94 INT_FITS_IN_JSID(int32_t i)
96 return i >= 0;
99 static MOZ_ALWAYS_INLINE jsid
100 INT_TO_JSID(int32_t i)
102 jsid id;
103 MOZ_ASSERT(INT_FITS_IN_JSID(i));
104 JSID_BITS(id) = ((i << 1) | JSID_TYPE_INT);
105 return id;
108 static MOZ_ALWAYS_INLINE bool
109 JSID_IS_SYMBOL(jsid id)
111 return (JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_SYMBOL &&
112 JSID_BITS(id) != JSID_TYPE_SYMBOL;
115 static MOZ_ALWAYS_INLINE JS::Symbol*
116 JSID_TO_SYMBOL(jsid id)
118 MOZ_ASSERT(JSID_IS_SYMBOL(id));
119 return (JS::Symbol*)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK);
122 static MOZ_ALWAYS_INLINE jsid
123 SYMBOL_TO_JSID(JS::Symbol* sym)
125 jsid id;
126 MOZ_ASSERT(sym != nullptr);
127 MOZ_ASSERT((size_t(sym) & JSID_TYPE_MASK) == 0);
128 MOZ_ASSERT(!js::gc::IsInsideNursery(reinterpret_cast<js::gc::Cell*>(sym)));
129 MOZ_ASSERT(!JS::IsPoisonedPtr(sym));
130 JSID_BITS(id) = (size_t(sym) | JSID_TYPE_SYMBOL);
131 return id;
134 static MOZ_ALWAYS_INLINE bool
135 JSID_IS_GCTHING(jsid id)
137 return JSID_IS_STRING(id) || JSID_IS_SYMBOL(id);
140 static MOZ_ALWAYS_INLINE JS::GCCellPtr
141 JSID_TO_GCTHING(jsid id)
143 void* thing = (void*)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK);
144 if (JSID_IS_STRING(id))
145 return JS::GCCellPtr(thing, JSTRACE_STRING);
146 MOZ_ASSERT(JSID_IS_SYMBOL(id));
147 return JS::GCCellPtr(thing, JSTRACE_SYMBOL);
150 static MOZ_ALWAYS_INLINE bool
151 JSID_IS_VOID(const jsid id)
153 MOZ_ASSERT_IF(((size_t)JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_VOID,
154 JSID_BITS(id) == JSID_TYPE_VOID);
155 return (size_t)JSID_BITS(id) == JSID_TYPE_VOID;
158 static MOZ_ALWAYS_INLINE bool
159 JSID_IS_EMPTY(const jsid id)
161 return (size_t)JSID_BITS(id) == JSID_TYPE_SYMBOL;
164 extern JS_PUBLIC_DATA(const jsid) JSID_VOID;
165 extern JS_PUBLIC_DATA(const jsid) JSID_EMPTY;
167 extern JS_PUBLIC_DATA(const JS::HandleId) JSID_VOIDHANDLE;
168 extern JS_PUBLIC_DATA(const JS::HandleId) JSID_EMPTYHANDLE;
170 namespace js {
172 inline bool
173 IsPoisonedId(jsid id)
175 if (JSID_IS_STRING(id))
176 return JS::IsPoisonedPtr(JSID_TO_STRING(id));
177 if (JSID_IS_SYMBOL(id))
178 return JS::IsPoisonedPtr(JSID_TO_SYMBOL(id));
179 return false;
182 template <> struct GCMethods<jsid>
184 static jsid initial() { return JSID_VOID; }
185 static bool poisoned(jsid id) { return IsPoisonedId(id); }
186 static bool needsPostBarrier(jsid id) { return false; }
187 static void postBarrier(jsid* idp) {}
188 static void relocate(jsid* idp) {}
191 #undef id
195 #endif /* js_Id_h */