Fri, 16 Jan 2015 18:13:44 +0100
Integrate suggestion from review to improve consistency with existing code.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
michael@0 | 2 | * vim: set ts=8 sts=4 et sw=4 tw=99: |
michael@0 | 3 | * This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | #ifndef js_Id_h |
michael@0 | 8 | #define js_Id_h |
michael@0 | 9 | |
michael@0 | 10 | // A jsid is an identifier for a property or method of an object which is |
michael@0 | 11 | // either a 31-bit signed integer, interned string or object. |
michael@0 | 12 | // |
michael@0 | 13 | // Also, there is an additional jsid value, JSID_VOID, which does not occur in |
michael@0 | 14 | // JS scripts but may be used to indicate the absence of a valid jsid. A void |
michael@0 | 15 | // jsid is not a valid id and only arises as an exceptional API return value, |
michael@0 | 16 | // such as in JS_NextProperty. Embeddings must not pass JSID_VOID into JSAPI |
michael@0 | 17 | // entry points expecting a jsid and do not need to handle JSID_VOID in hooks |
michael@0 | 18 | // receiving a jsid except when explicitly noted in the API contract. |
michael@0 | 19 | // |
michael@0 | 20 | // A jsid is not implicitly convertible to or from a jsval; JS_ValueToId or |
michael@0 | 21 | // JS_IdToValue must be used instead. |
michael@0 | 22 | |
michael@0 | 23 | #include "mozilla/NullPtr.h" |
michael@0 | 24 | |
michael@0 | 25 | #include "jstypes.h" |
michael@0 | 26 | |
michael@0 | 27 | #include "js/HeapAPI.h" |
michael@0 | 28 | #include "js/RootingAPI.h" |
michael@0 | 29 | #include "js/TypeDecls.h" |
michael@0 | 30 | #include "js/Utility.h" |
michael@0 | 31 | |
michael@0 | 32 | struct jsid |
michael@0 | 33 | { |
michael@0 | 34 | size_t asBits; |
michael@0 | 35 | bool operator==(jsid rhs) const { return asBits == rhs.asBits; } |
michael@0 | 36 | bool operator!=(jsid rhs) const { return asBits != rhs.asBits; } |
michael@0 | 37 | }; |
michael@0 | 38 | #define JSID_BITS(id) (id.asBits) |
michael@0 | 39 | |
michael@0 | 40 | #define JSID_TYPE_STRING 0x0 |
michael@0 | 41 | #define JSID_TYPE_INT 0x1 |
michael@0 | 42 | #define JSID_TYPE_VOID 0x2 |
michael@0 | 43 | #define JSID_TYPE_OBJECT 0x4 |
michael@0 | 44 | #define JSID_TYPE_MASK 0x7 |
michael@0 | 45 | |
michael@0 | 46 | // Avoid using canonical 'id' for jsid parameters since this is a magic word in |
michael@0 | 47 | // Objective-C++ which, apparently, wants to be able to #include jsapi.h. |
michael@0 | 48 | #define id iden |
michael@0 | 49 | |
michael@0 | 50 | static MOZ_ALWAYS_INLINE bool |
michael@0 | 51 | JSID_IS_STRING(jsid id) |
michael@0 | 52 | { |
michael@0 | 53 | return (JSID_BITS(id) & JSID_TYPE_MASK) == 0; |
michael@0 | 54 | } |
michael@0 | 55 | |
michael@0 | 56 | static MOZ_ALWAYS_INLINE JSString * |
michael@0 | 57 | JSID_TO_STRING(jsid id) |
michael@0 | 58 | { |
michael@0 | 59 | MOZ_ASSERT(JSID_IS_STRING(id)); |
michael@0 | 60 | return (JSString *)JSID_BITS(id); |
michael@0 | 61 | } |
michael@0 | 62 | |
michael@0 | 63 | static MOZ_ALWAYS_INLINE bool |
michael@0 | 64 | JSID_IS_ZERO(jsid id) |
michael@0 | 65 | { |
michael@0 | 66 | return JSID_BITS(id) == 0; |
michael@0 | 67 | } |
michael@0 | 68 | |
michael@0 | 69 | static MOZ_ALWAYS_INLINE bool |
michael@0 | 70 | JSID_IS_INT(jsid id) |
michael@0 | 71 | { |
michael@0 | 72 | return !!(JSID_BITS(id) & JSID_TYPE_INT); |
michael@0 | 73 | } |
michael@0 | 74 | |
michael@0 | 75 | static MOZ_ALWAYS_INLINE int32_t |
michael@0 | 76 | JSID_TO_INT(jsid id) |
michael@0 | 77 | { |
michael@0 | 78 | MOZ_ASSERT(JSID_IS_INT(id)); |
michael@0 | 79 | return ((uint32_t)JSID_BITS(id)) >> 1; |
michael@0 | 80 | } |
michael@0 | 81 | |
michael@0 | 82 | #define JSID_INT_MIN 0 |
michael@0 | 83 | #define JSID_INT_MAX INT32_MAX |
michael@0 | 84 | |
michael@0 | 85 | static MOZ_ALWAYS_INLINE bool |
michael@0 | 86 | INT_FITS_IN_JSID(int32_t i) |
michael@0 | 87 | { |
michael@0 | 88 | return i >= 0; |
michael@0 | 89 | } |
michael@0 | 90 | |
michael@0 | 91 | static MOZ_ALWAYS_INLINE jsid |
michael@0 | 92 | INT_TO_JSID(int32_t i) |
michael@0 | 93 | { |
michael@0 | 94 | jsid id; |
michael@0 | 95 | MOZ_ASSERT(INT_FITS_IN_JSID(i)); |
michael@0 | 96 | JSID_BITS(id) = ((i << 1) | JSID_TYPE_INT); |
michael@0 | 97 | return id; |
michael@0 | 98 | } |
michael@0 | 99 | |
michael@0 | 100 | static MOZ_ALWAYS_INLINE bool |
michael@0 | 101 | JSID_IS_OBJECT(jsid id) |
michael@0 | 102 | { |
michael@0 | 103 | return (JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_OBJECT && |
michael@0 | 104 | (size_t)JSID_BITS(id) != JSID_TYPE_OBJECT; |
michael@0 | 105 | } |
michael@0 | 106 | |
michael@0 | 107 | static MOZ_ALWAYS_INLINE JSObject * |
michael@0 | 108 | JSID_TO_OBJECT(jsid id) |
michael@0 | 109 | { |
michael@0 | 110 | MOZ_ASSERT(JSID_IS_OBJECT(id)); |
michael@0 | 111 | return (JSObject *)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK); |
michael@0 | 112 | } |
michael@0 | 113 | |
michael@0 | 114 | static MOZ_ALWAYS_INLINE jsid |
michael@0 | 115 | OBJECT_TO_JSID(JSObject *obj) |
michael@0 | 116 | { |
michael@0 | 117 | jsid id; |
michael@0 | 118 | MOZ_ASSERT(obj != nullptr); |
michael@0 | 119 | MOZ_ASSERT(((size_t)obj & JSID_TYPE_MASK) == 0); |
michael@0 | 120 | JS_ASSERT(!js::gc::IsInsideNursery(js::gc::GetGCThingRuntime(obj), obj)); |
michael@0 | 121 | JSID_BITS(id) = ((size_t)obj | JSID_TYPE_OBJECT); |
michael@0 | 122 | return id; |
michael@0 | 123 | } |
michael@0 | 124 | |
michael@0 | 125 | static MOZ_ALWAYS_INLINE bool |
michael@0 | 126 | JSID_IS_GCTHING(jsid id) |
michael@0 | 127 | { |
michael@0 | 128 | return JSID_IS_STRING(id) || JSID_IS_OBJECT(id); |
michael@0 | 129 | } |
michael@0 | 130 | |
michael@0 | 131 | static MOZ_ALWAYS_INLINE void * |
michael@0 | 132 | JSID_TO_GCTHING(jsid id) |
michael@0 | 133 | { |
michael@0 | 134 | return (void *)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK); |
michael@0 | 135 | } |
michael@0 | 136 | |
michael@0 | 137 | static MOZ_ALWAYS_INLINE bool |
michael@0 | 138 | JSID_IS_VOID(const jsid id) |
michael@0 | 139 | { |
michael@0 | 140 | MOZ_ASSERT_IF(((size_t)JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_VOID, |
michael@0 | 141 | JSID_BITS(id) == JSID_TYPE_VOID); |
michael@0 | 142 | return ((size_t)JSID_BITS(id) == JSID_TYPE_VOID); |
michael@0 | 143 | } |
michael@0 | 144 | |
michael@0 | 145 | static MOZ_ALWAYS_INLINE bool |
michael@0 | 146 | JSID_IS_EMPTY(const jsid id) |
michael@0 | 147 | { |
michael@0 | 148 | return ((size_t)JSID_BITS(id) == JSID_TYPE_OBJECT); |
michael@0 | 149 | } |
michael@0 | 150 | |
michael@0 | 151 | #undef id |
michael@0 | 152 | |
michael@0 | 153 | extern JS_PUBLIC_DATA(const jsid) JSID_VOID; |
michael@0 | 154 | extern JS_PUBLIC_DATA(const jsid) JSID_EMPTY; |
michael@0 | 155 | |
michael@0 | 156 | extern JS_PUBLIC_DATA(const JS::HandleId) JSID_VOIDHANDLE; |
michael@0 | 157 | extern JS_PUBLIC_DATA(const JS::HandleId) JSID_EMPTYHANDLE; |
michael@0 | 158 | |
michael@0 | 159 | namespace js { |
michael@0 | 160 | |
michael@0 | 161 | inline bool |
michael@0 | 162 | IsPoisonedId(jsid iden) |
michael@0 | 163 | { |
michael@0 | 164 | if (JSID_IS_STRING(iden)) |
michael@0 | 165 | return JS::IsPoisonedPtr(JSID_TO_STRING(iden)); |
michael@0 | 166 | if (JSID_IS_OBJECT(iden)) |
michael@0 | 167 | return JS::IsPoisonedPtr(JSID_TO_OBJECT(iden)); |
michael@0 | 168 | return false; |
michael@0 | 169 | } |
michael@0 | 170 | |
michael@0 | 171 | template <> struct GCMethods<jsid> |
michael@0 | 172 | { |
michael@0 | 173 | static jsid initial() { return JSID_VOID; } |
michael@0 | 174 | static ThingRootKind kind() { return THING_ROOT_ID; } |
michael@0 | 175 | static bool poisoned(jsid id) { return IsPoisonedId(id); } |
michael@0 | 176 | static bool needsPostBarrier(jsid id) { return false; } |
michael@0 | 177 | #ifdef JSGC_GENERATIONAL |
michael@0 | 178 | static void postBarrier(jsid *idp) {} |
michael@0 | 179 | static void relocate(jsid *idp) {} |
michael@0 | 180 | #endif |
michael@0 | 181 | }; |
michael@0 | 182 | |
michael@0 | 183 | } |
michael@0 | 184 | |
michael@0 | 185 | #endif /* js_Id_h */ |