1 : /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=4 sw=4 et tw=99 ft=cpp:
3 : *
4 : * ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
7 : * The contents of this file are subject to the Mozilla Public License Version
8 : * 1.1 (the "License"); you may not use this file except in compliance with
9 : * the License. You may obtain a copy of the License at
10 : * http://www.mozilla.org/MPL/
11 : *
12 : * Software distributed under the License is distributed on an "AS IS" basis,
13 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 : * for the specific language governing rights and limitations under the
15 : * License.
16 : *
17 : * The Original Code is SpiderMonkey JavaScript engine.
18 : *
19 : * The Initial Developer of the Original Code is
20 : * Mozilla Corporation.
21 : * Portions created by the Initial Developer are Copyright (C) 2011
22 : * the Initial Developer. All Rights Reserved.
23 : *
24 : * Contributor(s):
25 : * Chris Leary <cdleary@mozilla.com>
26 : *
27 : * Alternatively, the contents of this file may be used under the terms of
28 : * either the GNU General Public License Version 2 or later (the "GPL"), or
29 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 : * in which case the provisions of the GPL or the LGPL are applicable instead
31 : * of those above. If you wish to allow use of your version of this file only
32 : * under the terms of either the GPL or the LGPL, and not to allow others to
33 : * use your version of this file under the terms of the MPL, indicate your
34 : * decision by deleting the provisions above and replace them with the notice
35 : * and other provisions required by the GPL or the LGPL. If you do not delete
36 : * the provisions above, a recipient may use your version of this file under
37 : * the terms of any one of the MPL, the GPL or the LGPL.
38 : *
39 : * ***** END LICENSE BLOCK ***** */
40 :
41 : #include "ParseMaps-inl.h"
42 : #include "jscompartment.h"
43 :
44 : using namespace js;
45 :
46 : void
47 0 : ParseMapPool::checkInvariants()
48 : {
49 : /*
50 : * Having all values be of the same size permits us to easily reuse the
51 : * allocated space for each of the map types.
52 : */
53 : JS_STATIC_ASSERT(sizeof(Definition *) == sizeof(jsatomid));
54 : JS_STATIC_ASSERT(sizeof(Definition *) == sizeof(DefnOrHeader));
55 : JS_STATIC_ASSERT(sizeof(AtomDefnMap::Entry) == sizeof(AtomIndexMap::Entry));
56 : JS_STATIC_ASSERT(sizeof(AtomDefnMap::Entry) == sizeof(AtomDOHMap::Entry));
57 : JS_STATIC_ASSERT(sizeof(AtomMapT::Entry) == sizeof(AtomDOHMap::Entry));
58 : /* Ensure that the HasTable::clear goes quickly via memset. */
59 : JS_STATIC_ASSERT(tl::IsPodType<AtomIndexMap::WordMap::Entry>::result);
60 : JS_STATIC_ASSERT(tl::IsPodType<AtomDOHMap::WordMap::Entry>::result);
61 : JS_STATIC_ASSERT(tl::IsPodType<AtomDefnMap::WordMap::Entry>::result);
62 0 : }
63 :
64 : void
65 22498 : ParseMapPool::purgeAll()
66 : {
67 253842 : for (void **it = all.begin(), **end = all.end(); it != end; ++it)
68 231344 : cx->delete_<AtomMapT>(asAtomMap(*it));
69 :
70 22498 : all.clearAndFree();
71 22498 : recyclable.clearAndFree();
72 22498 : }
73 :
74 : void *
75 231344 : ParseMapPool::allocateFresh()
76 : {
77 231344 : size_t newAllLength = all.length() + 1;
78 231344 : if (!all.reserve(newAllLength) || !recyclable.reserve(newAllLength))
79 0 : return NULL;
80 :
81 231344 : AtomMapT *map = cx->new_<AtomMapT>(cx);
82 231344 : if (!map)
83 0 : return NULL;
84 :
85 231344 : all.infallibleAppend(map);
86 231344 : return (void *) map;
87 : }
88 :
89 : #ifdef DEBUG
90 : void
91 0 : AtomDecls::dump()
92 : {
93 0 : for (AtomDOHRange r = map->all(); !r.empty(); r.popFront()) {
94 0 : fprintf(stderr, "atom: ");
95 0 : js_DumpAtom(r.front().key());
96 0 : const DefnOrHeader &doh = r.front().value();
97 0 : if (doh.isHeader()) {
98 0 : AtomDeclNode *node = doh.header();
99 0 : do {
100 0 : fprintf(stderr, " node: %p\n", (void *) node);
101 0 : fprintf(stderr, " defn: %p\n", (void *) node->defn);
102 0 : node = node->next;
103 : } while (node);
104 : } else {
105 0 : fprintf(stderr, " defn: %p\n", (void *) doh.defn());
106 : }
107 : }
108 0 : }
109 :
110 : void
111 0 : DumpAtomDefnMap(const AtomDefnMapPtr &map)
112 : {
113 0 : if (map->empty()) {
114 0 : fprintf(stderr, "empty\n");
115 0 : return;
116 : }
117 :
118 0 : for (AtomDefnRange r = map->all(); !r.empty(); r.popFront()) {
119 0 : fprintf(stderr, "atom: ");
120 0 : js_DumpAtom(r.front().key());
121 0 : fprintf(stderr, "defn: %p\n", (void *) r.front().value());
122 : }
123 : }
124 : #endif
125 :
126 : AtomDeclNode *
127 754363 : AtomDecls::allocNode(Definition *defn)
128 : {
129 754363 : AtomDeclNode *p = cx->tempLifoAlloc().new_<AtomDeclNode>(defn);
130 754363 : if (!p) {
131 0 : js_ReportOutOfMemory(cx);
132 0 : return NULL;
133 : }
134 754363 : return p;
135 : }
136 :
137 : bool
138 751004 : AtomDecls::addShadow(JSAtom *atom, Definition *defn)
139 : {
140 751004 : AtomDeclNode *node = allocNode(defn);
141 751004 : if (!node)
142 0 : return false;
143 :
144 751004 : AtomDOHAddPtr p = map->lookupForAdd(atom);
145 751004 : if (!p)
146 745240 : return map->add(p, atom, DefnOrHeader(node));
147 :
148 : AtomDeclNode *toShadow;
149 5764 : if (p.value().isHeader()) {
150 2405 : toShadow = p.value().header();
151 : } else {
152 3359 : toShadow = allocNode(p.value().defn());
153 3359 : if (!toShadow)
154 0 : return false;
155 : }
156 5764 : node->next = toShadow;
157 5764 : p.value() = DefnOrHeader(node);
158 5764 : return true;
159 : }
160 :
161 : AtomDeclNode *
162 0 : AtomDecls::lastAsNode(DefnOrHeader *doh)
163 : {
164 0 : if (doh->isHeader()) {
165 0 : AtomDeclNode *last = doh->header();
166 0 : while (last->next)
167 0 : last = last->next;
168 0 : return last;
169 : }
170 :
171 : /* Otherwise, we need to turn the existing defn into a node. */
172 0 : AtomDeclNode *node = allocNode(doh->defn());
173 0 : if (!node)
174 0 : return NULL;
175 0 : *doh = DefnOrHeader(node);
176 0 : return node;
177 : }
178 :
179 : bool
180 0 : AtomDecls::addHoist(JSAtom *atom, Definition *defn)
181 : {
182 0 : AtomDeclNode *node = allocNode(defn);
183 0 : if (!node)
184 0 : return false;
185 :
186 0 : AtomDOHAddPtr p = map->lookupForAdd(atom);
187 0 : if (p) {
188 0 : AtomDeclNode *last = lastAsNode(&p.value());
189 0 : if (!last)
190 0 : return false;
191 0 : last->next = node;
192 0 : return true;
193 : }
194 :
195 0 : return map->add(p, atom, DefnOrHeader(node));
196 : }
|