michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef jsatominlines_h michael@0: #define jsatominlines_h michael@0: michael@0: #include "jsatom.h" michael@0: michael@0: #include "mozilla/PodOperations.h" michael@0: #include "mozilla/RangedPtr.h" michael@0: michael@0: #include "jscntxt.h" michael@0: #include "jsnum.h" michael@0: michael@0: #include "vm/String.h" michael@0: michael@0: inline JSAtom * michael@0: js::AtomStateEntry::asPtr() const michael@0: { michael@0: JS_ASSERT(bits != 0); michael@0: JSAtom *atom = reinterpret_cast(bits & NO_TAG_MASK); michael@0: JSString::readBarrier(atom); michael@0: return atom; michael@0: } michael@0: michael@0: namespace js { michael@0: michael@0: inline jsid michael@0: AtomToId(JSAtom *atom) michael@0: { michael@0: JS_STATIC_ASSERT(JSID_INT_MIN == 0); michael@0: michael@0: uint32_t index; michael@0: if (atom->isIndex(&index) && index <= JSID_INT_MAX) michael@0: return INT_TO_JSID(int32_t(index)); michael@0: michael@0: return JSID_FROM_BITS(size_t(atom)); michael@0: } michael@0: michael@0: inline bool michael@0: ValueToIdPure(const Value &v, jsid *id) michael@0: { michael@0: int32_t i; michael@0: if (ValueFitsInInt32(v, &i) && INT_FITS_IN_JSID(i)) { michael@0: *id = INT_TO_JSID(i); michael@0: return true; michael@0: } michael@0: michael@0: if (!v.isString() || !v.toString()->isAtom()) michael@0: return false; michael@0: michael@0: *id = AtomToId(&v.toString()->asAtom()); michael@0: return true; michael@0: } michael@0: michael@0: template michael@0: inline bool michael@0: ValueToId(JSContext* cx, typename MaybeRooted::HandleType v, michael@0: typename MaybeRooted::MutableHandleType idp) michael@0: { michael@0: int32_t i; michael@0: if (ValueFitsInInt32(v, &i) && INT_FITS_IN_JSID(i)) { michael@0: idp.set(INT_TO_JSID(i)); michael@0: return true; michael@0: } michael@0: michael@0: JSAtom *atom = ToAtom(cx, v); michael@0: if (!atom) michael@0: return false; michael@0: michael@0: idp.set(AtomToId(atom)); michael@0: return true; michael@0: } michael@0: michael@0: /* michael@0: * Write out character representing |index| to the memory just before |end|. michael@0: * Thus |*end| is not touched, but |end[-1]| and earlier are modified as michael@0: * appropriate. There must be at least js::UINT32_CHAR_BUFFER_LENGTH elements michael@0: * before |end| to avoid buffer underflow. The start of the characters written michael@0: * is returned and is necessarily before |end|. michael@0: */ michael@0: template michael@0: inline mozilla::RangedPtr michael@0: BackfillIndexInCharBuffer(uint32_t index, mozilla::RangedPtr end) michael@0: { michael@0: #ifdef DEBUG michael@0: /* michael@0: * Assert that the buffer we're filling will hold as many characters as we michael@0: * could write out, by dereferencing the index that would hold the most michael@0: * significant digit. michael@0: */ michael@0: (void) *(end - UINT32_CHAR_BUFFER_LENGTH); michael@0: #endif michael@0: michael@0: do { michael@0: uint32_t next = index / 10, digit = index % 10; michael@0: *--end = '0' + digit; michael@0: index = next; michael@0: } while (index > 0); michael@0: michael@0: return end; michael@0: } michael@0: michael@0: bool michael@0: IndexToIdSlow(ExclusiveContext *cx, uint32_t index, MutableHandleId idp); michael@0: michael@0: inline bool michael@0: IndexToId(ExclusiveContext *cx, uint32_t index, MutableHandleId idp) michael@0: { michael@0: if (index <= JSID_INT_MAX) { michael@0: idp.set(INT_TO_JSID(index)); michael@0: return true; michael@0: } michael@0: michael@0: return IndexToIdSlow(cx, index, idp); michael@0: } michael@0: michael@0: static MOZ_ALWAYS_INLINE JSFlatString * michael@0: IdToString(JSContext *cx, jsid id) michael@0: { michael@0: if (JSID_IS_STRING(id)) michael@0: return JSID_TO_ATOM(id); michael@0: michael@0: if (MOZ_LIKELY(JSID_IS_INT(id))) michael@0: return Int32ToString(cx, JSID_TO_INT(id)); michael@0: michael@0: RootedValue idv(cx, IdToValue(id)); michael@0: JSString *str = ToStringSlow(cx, idv); michael@0: if (!str) michael@0: return nullptr; michael@0: michael@0: return str->ensureFlat(cx); michael@0: } michael@0: michael@0: inline michael@0: AtomHasher::Lookup::Lookup(const JSAtom *atom) michael@0: : chars(atom->chars()), length(atom->length()), atom(atom) michael@0: { michael@0: hash = mozilla::HashString(chars, length); michael@0: } michael@0: michael@0: inline bool michael@0: AtomHasher::match(const AtomStateEntry &entry, const Lookup &lookup) michael@0: { michael@0: JSAtom *key = entry.asPtr(); michael@0: if (lookup.atom) michael@0: return lookup.atom == key; michael@0: if (key->length() != lookup.length) michael@0: return false; michael@0: return mozilla::PodEqual(key->chars(), lookup.chars, lookup.length); michael@0: } michael@0: michael@0: inline Handle michael@0: TypeName(JSType type, const JSAtomState &names) michael@0: { michael@0: JS_ASSERT(type < JSTYPE_LIMIT); michael@0: JS_STATIC_ASSERT(offsetof(JSAtomState, undefined) + michael@0: JSTYPE_LIMIT * sizeof(FixedHeapPtr) <= michael@0: sizeof(JSAtomState)); michael@0: JS_STATIC_ASSERT(JSTYPE_VOID == 0); michael@0: return (&names.undefined)[type]; michael@0: } michael@0: michael@0: inline Handle michael@0: ClassName(JSProtoKey key, JSAtomState &atomState) michael@0: { michael@0: JS_ASSERT(key < JSProto_LIMIT); michael@0: JS_STATIC_ASSERT(offsetof(JSAtomState, Null) + michael@0: JSProto_LIMIT * sizeof(FixedHeapPtr) <= michael@0: sizeof(JSAtomState)); michael@0: JS_STATIC_ASSERT(JSProto_Null == 0); michael@0: return (&atomState.Null)[key]; michael@0: } michael@0: michael@0: inline Handle michael@0: ClassName(JSProtoKey key, JSRuntime *rt) michael@0: { michael@0: return ClassName(key, *rt->commonNames); michael@0: } michael@0: michael@0: inline Handle michael@0: ClassName(JSProtoKey key, ExclusiveContext *cx) michael@0: { michael@0: return ClassName(key, cx->names()); michael@0: } michael@0: michael@0: } // namespace js michael@0: michael@0: #endif /* jsatominlines_h */