blob: 332927be4764db01e7d82a9095930c9267c9d214 [file] [log] [blame]
/* -*- 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 "jscntxt.h"
#include "FullParseHandler.h"
#include "SyntaxParseHandler.h"
#include "ParseMaps-inl.h"
#include "vm/String-inl.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<AtomIndexMap::WordMap::Entry>::value);
JS_STATIC_ASSERT(mozilla::IsPod<AtomDefnListMap::WordMap::Entry>::value);
JS_STATIC_ASSERT(mozilla::IsPod<AtomDefnMap::WordMap::Entry>::value);
}
void
ParseMapPool::purgeAll()
{
for (void **it = all.begin(), **end = all.end(); it != end; ++it)
js_delete<AtomMapT>(asAtomMap(*it));
all.clearAndFree();
recyclable.clearAndFree();
}
void *
ParseMapPool::allocateFresh()
{
size_t newAllLength = all.length() + 1;
if (!all.reserve(newAllLength) || !recyclable.reserve(newAllLength))
return NULL;
AtomMapT *map = js_new<AtomMapT>();
if (!map)
return NULL;
all.infallibleAppend(map);
return (void *) map;
}
DefinitionList::Node *
DefinitionList::allocNode(JSContext *cx, uintptr_t head, Node *tail)
{
Node *result = cx->tempLifoAlloc().new_<Node>(head, tail);
if (!result)
js_ReportOutOfMemory(cx);
return result;
}
#ifdef DEBUG
template <typename ParseHandler>
void
AtomDecls<ParseHandler>::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<ParseHandler>());
}
}
}
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<FullParseHandler>());
}
}
#endif
template <typename ParseHandler>
bool
AtomDecls<ParseHandler>::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<ParseHandler>(cx, defn);
}
void
frontend::InitAtomMap(JSContext *cx, 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<FullParseHandler>;
template class js::frontend::AtomDecls<SyntaxParseHandler>;