js/public/Id.h

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

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 */

mercurial