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
16 * The Original Code is Mozilla Communicator client code, released
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.
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___
51 #include "jscntxtinlines.h"
54 js::Shape::freeTable(JSContext *cx)
57 cx->destroy(getTable());
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;
70 emptyShapes = (js::EmptyShape**)
71 cx->calloc(sizeof(js::EmptyShape*) * js::gc::JS_FINALIZE_OBJECT_LIMIT);
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);
87 JS_ASSERT(aclasp == emptyShapes[0]->getClass());
89 if (!emptyShapes[i]) {
90 emptyShapes[i] = js::EmptyShape::create(cx, aclasp);
95 return emptyShapes[i];
99 JSObject::canProvideEmptyShape(js::Class *aclasp)
101 return !emptyShapes || emptyShapes[0]->getClass() == aclasp;
105 JSObject::updateShape(JSContext *cx)
107 JS_ASSERT(isNative());
108 js::LeaveTraceIfGlobalObject(cx, this);
110 setOwnShape(js_GenerateShape(cx));
112 objShape = lastProp->shape;
116 JSObject::updateFlags(const js::Shape *shape, bool isDefinitelyAtom)
119 if (!isDefinitelyAtom && js_IdIsIndex(shape->id, &index))
122 if (shape->isMethod())
127 JSObject::extend(JSContext *cx, const js::Shape *shape, bool isDefinitelyAtom)
129 setLastProperty(shape);
130 updateFlags(shape, isDefinitelyAtom);
135 JSObject::trace(JSTracer *trc)
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;
155 newShape = js_RegenerateShapeForGC(cx->runtime);
156 JS_ASSERT(newShape != shape->shape);
161 /* Trace our property tree or dictionary ancestor line. */
164 } while ((shape = shape->parent) != NULL);
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());
183 Shape::Shape(JSCompartment *comp, Class *aclasp)
184 : JSObjectMap(js_GenerateShape(comp->rt), JSSLOT_FREE(aclasp)),
185 numLinearSearches(0),
189 slot(SHAPE_INVALID_SLOT),
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);
206 hash = JS_ROTATE_LEFT32(hash, 4) ^ jsuword(rawGetter);
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);
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);
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 &&
236 ((flags ^ aflags) & PUBLIC_FLAGS) == 0 &&
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);
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);
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);
286 EmptyShape::EmptyShape(JSCompartment *comp, js::Class *aclasp)
287 : js::Shape(comp, aclasp)
290 if (comp->rt->meterEmptyShapes())
291 comp->emptyShapes.put(this);
297 #endif /* jsscopeinlines_h___ */