diff -r 000000000000 -r 6474c204b198 js/src/frontend/ParseMaps.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/js/src/frontend/ParseMaps.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,136 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "frontend/ParseMaps-inl.h" + +#include "jscntxt.h" + +#include "frontend/FullParseHandler.h" +#include "frontend/SyntaxParseHandler.h" + +using namespace js; +using namespace js::frontend; + +void +ParseMapPool::checkInvariants() +{ + /* + * Having all values be of the same size permits us to easily reuse the + * allocated space for each of the map types. + */ + JS_STATIC_ASSERT(sizeof(Definition *) == sizeof(jsatomid)); + JS_STATIC_ASSERT(sizeof(Definition *) == sizeof(DefinitionList)); + JS_STATIC_ASSERT(sizeof(AtomDefnMap::Entry) == sizeof(AtomIndexMap::Entry)); + JS_STATIC_ASSERT(sizeof(AtomDefnMap::Entry) == sizeof(AtomDefnListMap::Entry)); + JS_STATIC_ASSERT(sizeof(AtomMapT::Entry) == sizeof(AtomDefnListMap::Entry)); + /* Ensure that the HasTable::clear goes quickly via memset. */ + JS_STATIC_ASSERT(mozilla::IsPod::value); + JS_STATIC_ASSERT(mozilla::IsPod::value); + JS_STATIC_ASSERT(mozilla::IsPod::value); +} + +void +ParseMapPool::purgeAll() +{ + for (void **it = all.begin(), **end = all.end(); it != end; ++it) + js_delete(asAtomMap(*it)); + + all.clearAndFree(); + recyclable.clearAndFree(); +} + +void * +ParseMapPool::allocateFresh() +{ + size_t newAllLength = all.length() + 1; + if (!all.reserve(newAllLength) || !recyclable.reserve(newAllLength)) + return nullptr; + + AtomMapT *map = js_new(); + if (!map) + return nullptr; + + all.infallibleAppend(map); + return (void *) map; +} + +DefinitionList::Node * +DefinitionList::allocNode(ExclusiveContext *cx, LifoAlloc &alloc, uintptr_t head, Node *tail) +{ + Node *result = alloc.new_(head, tail); + if (!result) + js_ReportOutOfMemory(cx); + return result; +} + +#ifdef DEBUG +template +void +AtomDecls::dump() +{ + for (AtomDefnListRange r = map->all(); !r.empty(); r.popFront()) { + fprintf(stderr, "atom: "); + js_DumpAtom(r.front().key()); + const DefinitionList &dlist = r.front().value(); + for (DefinitionList::Range dr = dlist.all(); !dr.empty(); dr.popFront()) { + fprintf(stderr, " defn: %p\n", (void *) dr.front()); + } + } +} + +void +DumpAtomDefnMap(const AtomDefnMapPtr &map) +{ + if (map->empty()) { + fprintf(stderr, "empty\n"); + return; + } + + for (AtomDefnRange r = map->all(); !r.empty(); r.popFront()) { + fprintf(stderr, "atom: "); + js_DumpAtom(r.front().key()); + fprintf(stderr, "defn: %p\n", (void *) r.front().value().get()); + } +} +#endif + +template +bool +AtomDecls::addShadow(JSAtom *atom, typename ParseHandler::DefinitionNode defn) +{ + AtomDefnListAddPtr p = map->lookupForAdd(atom); + if (!p) + return map->add(p, atom, DefinitionList(ParseHandler::definitionToBits(defn))); + + return p.value().pushFront(cx, alloc, defn); +} + +void +frontend::InitAtomMap(frontend::AtomIndexMap *indices, HeapPtrAtom *atoms) +{ + if (indices->isMap()) { + typedef AtomIndexMap::WordMap WordMap; + const WordMap &wm = indices->asMap(); + for (WordMap::Range r = wm.all(); !r.empty(); r.popFront()) { + JSAtom *atom = r.front().key(); + jsatomid index = r.front().value(); + JS_ASSERT(index < indices->count()); + atoms[index].init(atom); + } + } else { + for (const AtomIndexMap::InlineElem *it = indices->asInline(), *end = indices->inlineEnd(); + it != end; ++it) { + JSAtom *atom = it->key; + if (!atom) + continue; + JS_ASSERT(it->value < indices->count()); + atoms[it->value].init(atom); + } + } +} + +template class js::frontend::AtomDecls; +template class js::frontend::AtomDecls;