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
)
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
, false));
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
);
150 shape
->setRegenFlag();
153 uint32 newShape
= shape
->shape
;
155 newShape
= js_RegenerateShapeForGC(cx
);
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::PropertyOp setter
, uint32 slot
, uintN attrs
,
171 uintN flags
, intN shortid
, uint32 shape
, uint32 slotSpan
)
172 : JSObjectMap(shape
, slotSpan
),
173 numSearches(0), table(NULL
), 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(JSContext
*cx
, Class
*aclasp
)
184 : JSObjectMap(js_GenerateShape(cx
, false), JSSLOT_FREE(aclasp
)), numSearches(0), table(NULL
),
185 id(JSID_EMPTY
), clasp(aclasp
), rawSetter(NULL
), slot(SHAPE_INVALID_SLOT
), attrs(0),
186 flags(SHARED_EMPTY
), shortid(0), parent(NULL
)
194 JSDHashNumber hash
= 0;
196 /* Accumulate from least to most random so the low bits are most random. */
197 JS_ASSERT_IF(isMethod(), !rawSetter
|| rawSetter
== js_watch_set
);
199 hash
= JS_ROTATE_LEFT32(hash
, 4) ^ jsuword(rawGetter
);
201 hash
= JS_ROTATE_LEFT32(hash
, 4) ^ jsuword(rawSetter
);
202 hash
= JS_ROTATE_LEFT32(hash
, 4) ^ (flags
& PUBLIC_FLAGS
);
203 hash
= JS_ROTATE_LEFT32(hash
, 4) ^ attrs
;
204 hash
= JS_ROTATE_LEFT32(hash
, 4) ^ shortid
;
205 hash
= JS_ROTATE_LEFT32(hash
, 4) ^ slot
;
206 hash
= JS_ROTATE_LEFT32(hash
, 4) ^ JSID_BITS(id
);
211 Shape::matches(const js::Shape
*other
) const
213 JS_ASSERT(!JSID_IS_VOID(id
));
214 JS_ASSERT(!JSID_IS_VOID(other
->id
));
215 return id
== other
->id
&&
216 matchesParamsAfterId(other
->rawGetter
, other
->rawSetter
, other
->slot
, other
->attrs
,
217 other
->flags
, other
->shortid
);
221 Shape::matchesParamsAfterId(js::PropertyOp agetter
, js::PropertyOp asetter
, uint32 aslot
,
222 uintN aattrs
, uintN aflags
, intN ashortid
) const
224 JS_ASSERT(!JSID_IS_VOID(id
));
225 return rawGetter
== agetter
&&
226 rawSetter
== asetter
&&
229 ((flags
^ aflags
) & PUBLIC_FLAGS
) == 0 &&
234 Shape::get(JSContext
* cx
, JSObject
*receiver
, JSObject
* obj
, JSObject
*pobj
, js::Value
* vp
) const
236 JS_ASSERT(!JSID_IS_VOID(this->id
));
237 JS_ASSERT(!hasDefaultGetter());
239 if (hasGetterValue()) {
240 JS_ASSERT(!isMethod());
241 js::Value fval
= getterValue();
242 return js::ExternalGetOrSet(cx
, receiver
, id
, fval
, JSACC_READ
, 0, 0, vp
);
246 vp
->setObject(methodObject());
247 return pobj
->methodReadBarrier(cx
, *this, vp
);
251 * |with (it) color;| ends up here, as do XML filter-expressions.
252 * Avoid exposing the With object to native getters.
254 if (obj
->getClass() == &js_WithClass
)
255 obj
= js_UnwrapWithObject(cx
, obj
);
256 return js::CallJSPropertyOp(cx
, getterOp(), obj
, SHAPE_USERID(this), vp
);
260 Shape::set(JSContext
* cx
, JSObject
* obj
, js::Value
* vp
) const
262 JS_ASSERT_IF(hasDefaultSetter(), hasGetterValue());
264 if (attrs
& JSPROP_SETTER
) {
265 js::Value fval
= setterValue();
266 return js::ExternalGetOrSet(cx
, obj
, id
, fval
, JSACC_WRITE
, 1, vp
, vp
);
269 if (attrs
& JSPROP_GETTER
)
270 return js_ReportGetterOnlyAssignment(cx
);
272 /* See the comment in js::Shape::get as to why we check for With. */
273 if (obj
->getClass() == &js_WithClass
)
274 obj
= js_UnwrapWithObject(cx
, obj
);
275 return js::CallJSPropertyOpSetter(cx
, setterOp(), obj
, SHAPE_USERID(this), vp
);
279 EmptyShape::EmptyShape(JSContext
*cx
, js::Class
*aclasp
)
280 : js::Shape(cx
, aclasp
)
283 if (cx
->runtime
->meterEmptyShapes())
284 cx
->runtime
->emptyShapes
.put(this);
290 #endif /* jsscopeinlines_h___ */