1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/public/Id.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,185 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef js_Id_h 1.11 +#define js_Id_h 1.12 + 1.13 +// A jsid is an identifier for a property or method of an object which is 1.14 +// either a 31-bit signed integer, interned string or object. 1.15 +// 1.16 +// Also, there is an additional jsid value, JSID_VOID, which does not occur in 1.17 +// JS scripts but may be used to indicate the absence of a valid jsid. A void 1.18 +// jsid is not a valid id and only arises as an exceptional API return value, 1.19 +// such as in JS_NextProperty. Embeddings must not pass JSID_VOID into JSAPI 1.20 +// entry points expecting a jsid and do not need to handle JSID_VOID in hooks 1.21 +// receiving a jsid except when explicitly noted in the API contract. 1.22 +// 1.23 +// A jsid is not implicitly convertible to or from a jsval; JS_ValueToId or 1.24 +// JS_IdToValue must be used instead. 1.25 + 1.26 +#include "mozilla/NullPtr.h" 1.27 + 1.28 +#include "jstypes.h" 1.29 + 1.30 +#include "js/HeapAPI.h" 1.31 +#include "js/RootingAPI.h" 1.32 +#include "js/TypeDecls.h" 1.33 +#include "js/Utility.h" 1.34 + 1.35 +struct jsid 1.36 +{ 1.37 + size_t asBits; 1.38 + bool operator==(jsid rhs) const { return asBits == rhs.asBits; } 1.39 + bool operator!=(jsid rhs) const { return asBits != rhs.asBits; } 1.40 +}; 1.41 +#define JSID_BITS(id) (id.asBits) 1.42 + 1.43 +#define JSID_TYPE_STRING 0x0 1.44 +#define JSID_TYPE_INT 0x1 1.45 +#define JSID_TYPE_VOID 0x2 1.46 +#define JSID_TYPE_OBJECT 0x4 1.47 +#define JSID_TYPE_MASK 0x7 1.48 + 1.49 +// Avoid using canonical 'id' for jsid parameters since this is a magic word in 1.50 +// Objective-C++ which, apparently, wants to be able to #include jsapi.h. 1.51 +#define id iden 1.52 + 1.53 +static MOZ_ALWAYS_INLINE bool 1.54 +JSID_IS_STRING(jsid id) 1.55 +{ 1.56 + return (JSID_BITS(id) & JSID_TYPE_MASK) == 0; 1.57 +} 1.58 + 1.59 +static MOZ_ALWAYS_INLINE JSString * 1.60 +JSID_TO_STRING(jsid id) 1.61 +{ 1.62 + MOZ_ASSERT(JSID_IS_STRING(id)); 1.63 + return (JSString *)JSID_BITS(id); 1.64 +} 1.65 + 1.66 +static MOZ_ALWAYS_INLINE bool 1.67 +JSID_IS_ZERO(jsid id) 1.68 +{ 1.69 + return JSID_BITS(id) == 0; 1.70 +} 1.71 + 1.72 +static MOZ_ALWAYS_INLINE bool 1.73 +JSID_IS_INT(jsid id) 1.74 +{ 1.75 + return !!(JSID_BITS(id) & JSID_TYPE_INT); 1.76 +} 1.77 + 1.78 +static MOZ_ALWAYS_INLINE int32_t 1.79 +JSID_TO_INT(jsid id) 1.80 +{ 1.81 + MOZ_ASSERT(JSID_IS_INT(id)); 1.82 + return ((uint32_t)JSID_BITS(id)) >> 1; 1.83 +} 1.84 + 1.85 +#define JSID_INT_MIN 0 1.86 +#define JSID_INT_MAX INT32_MAX 1.87 + 1.88 +static MOZ_ALWAYS_INLINE bool 1.89 +INT_FITS_IN_JSID(int32_t i) 1.90 +{ 1.91 + return i >= 0; 1.92 +} 1.93 + 1.94 +static MOZ_ALWAYS_INLINE jsid 1.95 +INT_TO_JSID(int32_t i) 1.96 +{ 1.97 + jsid id; 1.98 + MOZ_ASSERT(INT_FITS_IN_JSID(i)); 1.99 + JSID_BITS(id) = ((i << 1) | JSID_TYPE_INT); 1.100 + return id; 1.101 +} 1.102 + 1.103 +static MOZ_ALWAYS_INLINE bool 1.104 +JSID_IS_OBJECT(jsid id) 1.105 +{ 1.106 + return (JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_OBJECT && 1.107 + (size_t)JSID_BITS(id) != JSID_TYPE_OBJECT; 1.108 +} 1.109 + 1.110 +static MOZ_ALWAYS_INLINE JSObject * 1.111 +JSID_TO_OBJECT(jsid id) 1.112 +{ 1.113 + MOZ_ASSERT(JSID_IS_OBJECT(id)); 1.114 + return (JSObject *)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK); 1.115 +} 1.116 + 1.117 +static MOZ_ALWAYS_INLINE jsid 1.118 +OBJECT_TO_JSID(JSObject *obj) 1.119 +{ 1.120 + jsid id; 1.121 + MOZ_ASSERT(obj != nullptr); 1.122 + MOZ_ASSERT(((size_t)obj & JSID_TYPE_MASK) == 0); 1.123 + JS_ASSERT(!js::gc::IsInsideNursery(js::gc::GetGCThingRuntime(obj), obj)); 1.124 + JSID_BITS(id) = ((size_t)obj | JSID_TYPE_OBJECT); 1.125 + return id; 1.126 +} 1.127 + 1.128 +static MOZ_ALWAYS_INLINE bool 1.129 +JSID_IS_GCTHING(jsid id) 1.130 +{ 1.131 + return JSID_IS_STRING(id) || JSID_IS_OBJECT(id); 1.132 +} 1.133 + 1.134 +static MOZ_ALWAYS_INLINE void * 1.135 +JSID_TO_GCTHING(jsid id) 1.136 +{ 1.137 + return (void *)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK); 1.138 +} 1.139 + 1.140 +static MOZ_ALWAYS_INLINE bool 1.141 +JSID_IS_VOID(const jsid id) 1.142 +{ 1.143 + MOZ_ASSERT_IF(((size_t)JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_VOID, 1.144 + JSID_BITS(id) == JSID_TYPE_VOID); 1.145 + return ((size_t)JSID_BITS(id) == JSID_TYPE_VOID); 1.146 +} 1.147 + 1.148 +static MOZ_ALWAYS_INLINE bool 1.149 +JSID_IS_EMPTY(const jsid id) 1.150 +{ 1.151 + return ((size_t)JSID_BITS(id) == JSID_TYPE_OBJECT); 1.152 +} 1.153 + 1.154 +#undef id 1.155 + 1.156 +extern JS_PUBLIC_DATA(const jsid) JSID_VOID; 1.157 +extern JS_PUBLIC_DATA(const jsid) JSID_EMPTY; 1.158 + 1.159 +extern JS_PUBLIC_DATA(const JS::HandleId) JSID_VOIDHANDLE; 1.160 +extern JS_PUBLIC_DATA(const JS::HandleId) JSID_EMPTYHANDLE; 1.161 + 1.162 +namespace js { 1.163 + 1.164 +inline bool 1.165 +IsPoisonedId(jsid iden) 1.166 +{ 1.167 + if (JSID_IS_STRING(iden)) 1.168 + return JS::IsPoisonedPtr(JSID_TO_STRING(iden)); 1.169 + if (JSID_IS_OBJECT(iden)) 1.170 + return JS::IsPoisonedPtr(JSID_TO_OBJECT(iden)); 1.171 + return false; 1.172 +} 1.173 + 1.174 +template <> struct GCMethods<jsid> 1.175 +{ 1.176 + static jsid initial() { return JSID_VOID; } 1.177 + static ThingRootKind kind() { return THING_ROOT_ID; } 1.178 + static bool poisoned(jsid id) { return IsPoisonedId(id); } 1.179 + static bool needsPostBarrier(jsid id) { return false; } 1.180 +#ifdef JSGC_GENERATIONAL 1.181 + static void postBarrier(jsid *idp) {} 1.182 + static void relocate(jsid *idp) {} 1.183 +#endif 1.184 +}; 1.185 + 1.186 +} 1.187 + 1.188 +#endif /* js_Id_h */