Merge mozilla-central and tracemonkey. (a=blockers)
[mozilla-central.git] / js / src / jsscopeinlines.h
blob825b9a9db2879f8653193ef1c47b6a299140d77e
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is Mozilla Communicator client code, released
17 * March 31, 1998.
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1998
22 * the Initial Developer. All Rights Reserved.
24 * Contributor(s):
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #ifndef jsscopeinlines_h___
41 #define jsscopeinlines_h___
43 #include <new>
44 #include "jsbool.h"
45 #include "jscntxt.h"
46 #include "jsdbgapi.h"
47 #include "jsfun.h"
48 #include "jsobj.h"
49 #include "jsscope.h"
51 #include "jscntxtinlines.h"
53 inline void
54 js::Shape::freeTable(JSContext *cx)
56 if (hasTable()) {
57 cx->destroy(getTable());
58 setTable(NULL);
62 inline js::EmptyShape *
63 JSObject::getEmptyShape(JSContext *cx, js::Class *aclasp,
64 /* gc::FinalizeKind */ unsigned kind)
66 JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind <= js::gc::FINALIZE_OBJECT_LAST);
67 int i = kind - js::gc::FINALIZE_OBJECT0;
69 if (!emptyShapes) {
70 emptyShapes = (js::EmptyShape**)
71 cx->calloc(sizeof(js::EmptyShape*) * js::gc::JS_FINALIZE_OBJECT_LIMIT);
72 if (!emptyShapes)
73 return NULL;
76 * Always fill in emptyShapes[0], so canProvideEmptyShape works.
77 * Other empty shapes are filled in lazily.
79 emptyShapes[0] = js::EmptyShape::create(cx, aclasp);
80 if (!emptyShapes[0]) {
81 cx->free(emptyShapes);
82 emptyShapes = NULL;
83 return NULL;
87 JS_ASSERT(aclasp == emptyShapes[0]->getClass());
89 if (!emptyShapes[i]) {
90 emptyShapes[i] = js::EmptyShape::create(cx, aclasp);
91 if (!emptyShapes[i])
92 return NULL;
95 return emptyShapes[i];
98 inline bool
99 JSObject::canProvideEmptyShape(js::Class *aclasp)
101 return !emptyShapes || emptyShapes[0]->getClass() == aclasp;
104 inline void
105 JSObject::updateShape(JSContext *cx)
107 JS_ASSERT(isNative());
108 js::LeaveTraceIfGlobalObject(cx, this);
109 if (hasOwnShape())
110 setOwnShape(js_GenerateShape(cx));
111 else
112 objShape = lastProp->shape;
115 inline void
116 JSObject::updateFlags(const js::Shape *shape, bool isDefinitelyAtom)
118 jsuint index;
119 if (!isDefinitelyAtom && js_IdIsIndex(shape->id, &index))
120 setIndexed();
122 if (shape->isMethod())
123 setMethodBarrier();
126 inline void
127 JSObject::extend(JSContext *cx, const js::Shape *shape, bool isDefinitelyAtom)
129 setLastProperty(shape);
130 updateFlags(shape, isDefinitelyAtom);
131 updateShape(cx);
134 inline void
135 JSObject::trace(JSTracer *trc)
137 if (!isNative())
138 return;
140 JSContext *cx = trc->context;
141 js::Shape *shape = lastProp;
143 if (IS_GC_MARKING_TRACER(trc) && cx->runtime->gcRegenShapes) {
145 * Either this object has its own shape, which must be regenerated, or
146 * it must have the same shape as lastProp.
148 if (!shape->hasRegenFlag()) {
149 shape->shape = js_RegenerateShapeForGC(cx->runtime);
150 shape->setRegenFlag();
153 uint32 newShape = shape->shape;
154 if (hasOwnShape()) {
155 newShape = js_RegenerateShapeForGC(cx->runtime);
156 JS_ASSERT(newShape != shape->shape);
158 objShape = newShape;
161 /* Trace our property tree or dictionary ancestor line. */
162 do {
163 shape->trace(trc);
164 } while ((shape = shape->parent) != NULL);
167 namespace js {
169 inline
170 Shape::Shape(jsid id, js::PropertyOp getter, js::StrictPropertyOp setter, uint32 slot, uintN attrs,
171 uintN flags, intN shortid, uint32 shape, uint32 slotSpan)
172 : JSObjectMap(shape, slotSpan),
173 numLinearSearches(0), id(id), rawGetter(getter), rawSetter(setter), slot(slot),
174 attrs(uint8(attrs)), flags(uint8(flags)), shortid(int16(shortid)), parent(NULL)
176 JS_ASSERT_IF(slotSpan != SHAPE_INVALID_SLOT, slotSpan < JSObject::NSLOTS_LIMIT);
177 JS_ASSERT_IF(getter && (attrs & JSPROP_GETTER), getterObj->isCallable());
178 JS_ASSERT_IF(setter && (attrs & JSPROP_SETTER), setterObj->isCallable());
179 kids.setNull();
182 inline
183 Shape::Shape(JSCompartment *comp, Class *aclasp)
184 : JSObjectMap(js_GenerateShape(comp->rt), JSSLOT_FREE(aclasp)),
185 numLinearSearches(0),
186 id(JSID_EMPTY),
187 clasp(aclasp),
188 rawSetter(NULL),
189 slot(SHAPE_INVALID_SLOT),
190 attrs(0),
191 flags(SHARED_EMPTY),
192 shortid(0),
193 parent(NULL)
195 kids.setNull();
198 inline JSDHashNumber
199 Shape::hash() const
201 JSDHashNumber hash = 0;
203 /* Accumulate from least to most random so the low bits are most random. */
204 JS_ASSERT_IF(isMethod(), !rawSetter || rawSetter == js_watch_set);
205 if (rawGetter)
206 hash = JS_ROTATE_LEFT32(hash, 4) ^ jsuword(rawGetter);
207 if (rawSetter)
208 hash = JS_ROTATE_LEFT32(hash, 4) ^ jsuword(rawSetter);
209 hash = JS_ROTATE_LEFT32(hash, 4) ^ (flags & PUBLIC_FLAGS);
210 hash = JS_ROTATE_LEFT32(hash, 4) ^ attrs;
211 hash = JS_ROTATE_LEFT32(hash, 4) ^ shortid;
212 hash = JS_ROTATE_LEFT32(hash, 4) ^ slot;
213 hash = JS_ROTATE_LEFT32(hash, 4) ^ JSID_BITS(id);
214 return hash;
217 inline bool
218 Shape::matches(const js::Shape *other) const
220 JS_ASSERT(!JSID_IS_VOID(id));
221 JS_ASSERT(!JSID_IS_VOID(other->id));
222 return id == other->id &&
223 matchesParamsAfterId(other->rawGetter, other->rawSetter, other->slot, other->attrs,
224 other->flags, other->shortid);
227 inline bool
228 Shape::matchesParamsAfterId(js::PropertyOp agetter, js::StrictPropertyOp asetter, uint32 aslot,
229 uintN aattrs, uintN aflags, intN ashortid) const
231 JS_ASSERT(!JSID_IS_VOID(id));
232 return rawGetter == agetter &&
233 rawSetter == asetter &&
234 slot == aslot &&
235 attrs == aattrs &&
236 ((flags ^ aflags) & PUBLIC_FLAGS) == 0 &&
237 shortid == ashortid;
240 inline bool
241 Shape::get(JSContext* cx, JSObject *receiver, JSObject* obj, JSObject *pobj, js::Value* vp) const
243 JS_ASSERT(!JSID_IS_VOID(this->id));
244 JS_ASSERT(!hasDefaultGetter());
246 if (hasGetterValue()) {
247 JS_ASSERT(!isMethod());
248 js::Value fval = getterValue();
249 return js::ExternalGetOrSet(cx, receiver, id, fval, JSACC_READ, 0, 0, vp);
252 if (isMethod()) {
253 vp->setObject(methodObject());
254 return pobj->methodReadBarrier(cx, *this, vp);
258 * |with (it) color;| ends up here, as do XML filter-expressions.
259 * Avoid exposing the With object to native getters.
261 if (obj->getClass() == &js_WithClass)
262 obj = js_UnwrapWithObject(cx, obj);
263 return js::CallJSPropertyOp(cx, getterOp(), obj, SHAPE_USERID(this), vp);
266 inline bool
267 Shape::set(JSContext* cx, JSObject* obj, bool strict, js::Value* vp) const
269 JS_ASSERT_IF(hasDefaultSetter(), hasGetterValue());
271 if (attrs & JSPROP_SETTER) {
272 js::Value fval = setterValue();
273 return js::ExternalGetOrSet(cx, obj, id, fval, JSACC_WRITE, 1, vp, vp);
276 if (attrs & JSPROP_GETTER)
277 return js_ReportGetterOnlyAssignment(cx);
279 /* See the comment in js::Shape::get as to why we check for With. */
280 if (obj->getClass() == &js_WithClass)
281 obj = js_UnwrapWithObject(cx, obj);
282 return js::CallJSPropertyOpSetter(cx, setterOp(), obj, SHAPE_USERID(this), strict, vp);
285 inline
286 EmptyShape::EmptyShape(JSCompartment *comp, js::Class *aclasp)
287 : js::Shape(comp, aclasp)
289 #ifdef DEBUG
290 if (comp->rt->meterEmptyShapes())
291 comp->emptyShapes.put(this);
292 #endif
295 } /* namespace js */
297 #endif /* jsscopeinlines_h___ */