1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sw=4 et tw=99:
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 Mozilla Communicator client code, released
18 : * March 31, 1998.
19 : *
20 : * The Initial Developer of the Original Code is
21 : * Netscape Communications Corporation.
22 : * Portions created by the Initial Developer are Copyright (C) 1998
23 : * the Initial Developer. All Rights Reserved.
24 : *
25 : * Contributor(s):
26 : *
27 : * Alternatively, the contents of this file may be used under the terms of
28 : * either of the GNU General Public License Version 2 or later (the "GPL"),
29 : * or 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 : #ifndef jsobjinlines_h___
42 : #define jsobjinlines_h___
43 :
44 : #include <new>
45 :
46 : #include "jsapi.h"
47 : #include "jsarray.h"
48 : #include "jsbool.h"
49 : #include "jscntxt.h"
50 : #include "jsdate.h"
51 : #include "jsfun.h"
52 : #include "jsgcmark.h"
53 : #include "jsiter.h"
54 : #include "jslock.h"
55 : #include "jsnum.h"
56 : #include "jsobj.h"
57 : #include "jsprobes.h"
58 : #include "jspropertytree.h"
59 : #include "jsproxy.h"
60 : #include "jsscope.h"
61 : #include "jsstr.h"
62 : #include "jstypedarray.h"
63 : #include "jsxml.h"
64 : #include "jswrapper.h"
65 :
66 : #include "gc/Barrier.h"
67 : #include "js/TemplateLib.h"
68 :
69 : #include "vm/BooleanObject.h"
70 : #include "vm/GlobalObject.h"
71 : #include "vm/NumberObject.h"
72 : #include "vm/RegExpStatics.h"
73 : #include "vm/StringObject.h"
74 :
75 : #include "jsatominlines.h"
76 : #include "jsfuninlines.h"
77 : #include "jsgcinlines.h"
78 : #include "jsinferinlines.h"
79 : #include "jsscopeinlines.h"
80 : #include "jsscriptinlines.h"
81 :
82 : #include "gc/Barrier-inl.h"
83 :
84 : #include "vm/ObjectImpl-inl.h"
85 : #include "vm/RegExpStatics-inl.h"
86 : #include "vm/String-inl.h"
87 :
88 : inline bool
89 38700612 : JSObject::enumerate(JSContext *cx, JSIterateOp iterop, js::Value *statep, jsid *idp)
90 : {
91 38700612 : JSNewEnumerateOp op = getOps()->enumerate;
92 38700612 : return (op ? op : JS_EnumerateState)(cx, this, iterop, statep, idp);
93 : }
94 :
95 : inline bool
96 892635 : JSObject::defaultValue(JSContext *cx, JSType hint, js::Value *vp)
97 : {
98 892635 : JSConvertOp op = getClass()->convert;
99 892635 : bool ok = (op == JS_ConvertStub ? js::DefaultValue : op)(cx, this, hint, vp);
100 892635 : JS_ASSERT_IF(ok, vp->isPrimitive());
101 892635 : return ok;
102 : }
103 :
104 : inline JSType
105 28137 : JSObject::typeOf(JSContext *cx)
106 : {
107 28137 : js::TypeOfOp op = getOps()->typeOf;
108 28137 : return (op ? op : js_TypeOf)(cx, this);
109 : }
110 :
111 : inline JSObject *
112 1620169 : JSObject::thisObject(JSContext *cx)
113 : {
114 1620169 : JSObjectOp op = getOps()->thisObject;
115 1620169 : return op ? op(cx, this) : this;
116 : }
117 :
118 : inline JSBool
119 2812112 : JSObject::setGeneric(JSContext *cx, jsid id, js::Value *vp, JSBool strict)
120 : {
121 2812112 : if (getOps()->setGeneric)
122 1761478 : return nonNativeSetProperty(cx, id, vp, strict);
123 1050634 : return js_SetPropertyHelper(cx, this, id, 0, vp, strict);
124 : }
125 :
126 : inline JSBool
127 14138 : JSObject::setProperty(JSContext *cx, js::PropertyName *name, js::Value *vp, JSBool strict)
128 : {
129 14138 : return setGeneric(cx, ATOM_TO_JSID(name), vp, strict);
130 : }
131 :
132 : inline JSBool
133 22239 : JSObject::setElement(JSContext *cx, uint32_t index, js::Value *vp, JSBool strict)
134 : {
135 22239 : if (getOps()->setElement)
136 22238 : return nonNativeSetElement(cx, index, vp, strict);
137 1 : return js_SetElementHelper(cx, this, index, 0, vp, strict);
138 : }
139 :
140 : inline JSBool
141 0 : JSObject::setSpecial(JSContext *cx, js::SpecialId sid, js::Value *vp, JSBool strict)
142 : {
143 0 : return setGeneric(cx, SPECIALID_TO_JSID(sid), vp, strict);
144 : }
145 :
146 : inline JSBool
147 31914 : JSObject::setGenericAttributes(JSContext *cx, jsid id, unsigned *attrsp)
148 : {
149 31914 : js::types::MarkTypePropertyConfigured(cx, this, id);
150 31914 : js::GenericAttributesOp op = getOps()->setGenericAttributes;
151 31914 : return (op ? op : js_SetAttributes)(cx, this, id, attrsp);
152 : }
153 :
154 : inline JSBool
155 0 : JSObject::setPropertyAttributes(JSContext *cx, js::PropertyName *name, unsigned *attrsp)
156 : {
157 0 : return setGenericAttributes(cx, ATOM_TO_JSID(name), attrsp);
158 : }
159 :
160 : inline JSBool
161 0 : JSObject::setElementAttributes(JSContext *cx, uint32_t index, unsigned *attrsp)
162 : {
163 0 : js::ElementAttributesOp op = getOps()->setElementAttributes;
164 0 : return (op ? op : js_SetElementAttributes)(cx, this, index, attrsp);
165 : }
166 :
167 : inline JSBool
168 0 : JSObject::setSpecialAttributes(JSContext *cx, js::SpecialId sid, unsigned *attrsp)
169 : {
170 0 : return setGenericAttributes(cx, SPECIALID_TO_JSID(sid), attrsp);
171 : }
172 :
173 : inline bool
174 31914 : JSObject::changePropertyAttributes(JSContext *cx, js::Shape *shape, unsigned attrs)
175 : {
176 31914 : return !!changeProperty(cx, shape, attrs, 0, shape->getter(), shape->setter());
177 : }
178 :
179 : inline JSBool
180 21028366 : JSObject::getGeneric(JSContext *cx, JSObject *receiver, jsid id, js::Value *vp)
181 : {
182 21028366 : js::GenericIdOp op = getOps()->getGeneric;
183 21028366 : if (op) {
184 2282341 : if (!op(cx, this, receiver, id, vp))
185 18 : return false;
186 : } else {
187 18746025 : if (!js_GetProperty(cx, this, receiver, id, vp))
188 54 : return false;
189 : }
190 21028294 : return true;
191 : }
192 :
193 : inline JSBool
194 2379523 : JSObject::getProperty(JSContext *cx, JSObject *receiver, js::PropertyName *name, js::Value *vp)
195 : {
196 2379523 : return getGeneric(cx, receiver, ATOM_TO_JSID(name), vp);
197 : }
198 :
199 : inline JSBool
200 17624106 : JSObject::getGeneric(JSContext *cx, jsid id, js::Value *vp)
201 : {
202 17624106 : return getGeneric(cx, this, id, vp);
203 : }
204 :
205 : inline JSBool
206 2850927 : JSObject::getProperty(JSContext *cx, js::PropertyName *name, js::Value *vp)
207 : {
208 2850927 : return getGeneric(cx, ATOM_TO_JSID(name), vp);
209 : }
210 :
211 : inline bool
212 1548 : JSObject::deleteProperty(JSContext *cx, js::PropertyName *name, js::Value *rval, bool strict)
213 : {
214 1548 : jsid id = js_CheckForStringIndex(ATOM_TO_JSID(name));
215 1548 : js::types::AddTypePropertyId(cx, this, id, js::types::Type::UndefinedType());
216 1548 : js::types::MarkTypePropertyConfigured(cx, this, id);
217 1548 : js::DeletePropertyOp op = getOps()->deleteProperty;
218 1548 : return (op ? op : js_DeleteProperty)(cx, this, name, rval, strict);
219 : }
220 :
221 : inline bool
222 195138 : JSObject::deleteElement(JSContext *cx, uint32_t index, js::Value *rval, bool strict)
223 : {
224 : jsid id;
225 195138 : if (!js::IndexToId(cx, index, &id))
226 0 : return false;
227 195138 : js::types::AddTypePropertyId(cx, this, id, js::types::Type::UndefinedType());
228 195138 : js::types::MarkTypePropertyConfigured(cx, this, id);
229 195138 : js::DeleteElementOp op = getOps()->deleteElement;
230 195138 : return (op ? op : js_DeleteElement)(cx, this, index, rval, strict);
231 : }
232 :
233 : inline bool
234 0 : JSObject::deleteSpecial(JSContext *cx, js::SpecialId sid, js::Value *rval, bool strict)
235 : {
236 0 : jsid id = SPECIALID_TO_JSID(sid);
237 0 : js::types::AddTypePropertyId(cx, this, id, js::types::Type::UndefinedType());
238 0 : js::types::MarkTypePropertyConfigured(cx, this, id);
239 0 : js::DeleteSpecialOp op = getOps()->deleteSpecial;
240 0 : return (op ? op : js_DeleteSpecial)(cx, this, sid, rval, strict);
241 : }
242 :
243 : inline void
244 30978300 : JSObject::finalize(js::FreeOp *fop)
245 : {
246 30978300 : js::Probes::finalizeObject(this);
247 :
248 30978300 : if (!fop->onBackgroundThread()) {
249 : /*
250 : * Finalize obj first, in case it needs map and slots. Objects with
251 : * finalize hooks are not finalized in the background, as the class is
252 : * stored in the object's shape, which may have already been destroyed.
253 : */
254 30444269 : js::Class *clasp = getClass();
255 30444269 : if (clasp->finalize)
256 1831884 : clasp->finalize(fop, this);
257 : }
258 :
259 30978300 : finish(fop);
260 30978300 : }
261 :
262 : inline JSObject *
263 1043233097 : JSObject::getParent() const
264 : {
265 1043233097 : return lastProperty()->getObjectParent();
266 : }
267 :
268 : inline JSObject *
269 1989979 : JSObject::enclosingScope()
270 : {
271 1989979 : return isScope() ? &asScope().enclosingScope() : getParent();
272 : }
273 :
274 : inline bool
275 67617 : JSObject::isFixedSlot(size_t slot)
276 : {
277 67617 : JS_ASSERT(!isDenseArray());
278 67617 : return slot < numFixedSlots();
279 : }
280 :
281 : inline size_t
282 229294 : JSObject::dynamicSlotIndex(size_t slot)
283 : {
284 229294 : JS_ASSERT(!isDenseArray() && slot >= numFixedSlots());
285 229294 : return slot - numFixedSlots();
286 : }
287 :
288 : inline void
289 12034 : JSObject::setLastPropertyInfallible(const js::Shape *shape)
290 : {
291 12034 : JS_ASSERT(!shape->inDictionary());
292 12034 : JS_ASSERT(shape->compartment() == compartment());
293 12034 : JS_ASSERT(!inDictionaryMode());
294 12034 : JS_ASSERT(slotSpan() == shape->slotSpan());
295 12034 : JS_ASSERT(numFixedSlots() == shape->numFixedSlots());
296 :
297 12034 : shape_ = const_cast<js::Shape *>(shape);
298 12034 : }
299 :
300 : inline void
301 1224 : JSObject::removeLastProperty(JSContext *cx)
302 : {
303 1224 : JS_ASSERT(canRemoveLastProperty());
304 1224 : JS_ALWAYS_TRUE(setLastProperty(cx, lastProperty()->previous()));
305 1224 : }
306 :
307 : inline bool
308 2457 : JSObject::canRemoveLastProperty()
309 : {
310 : /*
311 : * Check that the information about the object stored in the last
312 : * property's base shape is consistent with that stored in the previous
313 : * shape. If not consistent, then the last property cannot be removed as it
314 : * will induce a change in the object itself, and the object must be
315 : * converted to dictionary mode instead. See BaseShape comment in jsscope.h
316 : */
317 2457 : JS_ASSERT(!inDictionaryMode());
318 2457 : const js::Shape *previous = lastProperty()->previous();
319 2457 : return previous->getObjectParent() == lastProperty()->getObjectParent()
320 2457 : && previous->getObjectFlags() == lastProperty()->getObjectFlags();
321 : }
322 :
323 : inline const js::HeapSlot *
324 182670 : JSObject::getRawSlots()
325 : {
326 182670 : JS_ASSERT(isGlobal());
327 182670 : return slots;
328 : }
329 :
330 : inline const js::Value &
331 24636283 : JSObject::getReservedSlot(unsigned index) const
332 : {
333 24636283 : JS_ASSERT(index < JSSLOT_FREE(getClass()));
334 24636283 : return getSlot(index);
335 : }
336 :
337 : inline js::HeapSlot &
338 146957 : JSObject::getReservedSlotRef(unsigned index)
339 : {
340 146957 : JS_ASSERT(index < JSSLOT_FREE(getClass()));
341 146957 : return getSlotRef(index);
342 : }
343 :
344 : inline void
345 6111062 : JSObject::setReservedSlot(unsigned index, const js::Value &v)
346 : {
347 6111062 : JS_ASSERT(index < JSSLOT_FREE(getClass()));
348 6111062 : setSlot(index, v);
349 6111062 : }
350 :
351 : inline void
352 100595 : JSObject::initReservedSlot(unsigned index, const js::Value &v)
353 : {
354 100595 : JS_ASSERT(index < JSSLOT_FREE(getClass()));
355 100595 : initSlot(index, v);
356 100595 : }
357 :
358 : inline void
359 450 : JSObject::prepareSlotRangeForOverwrite(size_t start, size_t end)
360 : {
361 900 : for (size_t i = start; i < end; i++)
362 450 : getSlotAddressUnchecked(i)->js::HeapSlot::~HeapSlot();
363 450 : }
364 :
365 : inline void
366 558739 : JSObject::prepareElementRangeForOverwrite(size_t start, size_t end)
367 : {
368 558739 : JS_ASSERT(isDenseArray());
369 558739 : JS_ASSERT(end <= getDenseArrayInitializedLength());
370 628087 : for (size_t i = start; i < end; i++)
371 69348 : elements[i].js::HeapSlot::~HeapSlot();
372 558739 : }
373 :
374 : inline uint32_t
375 41919127 : JSObject::getArrayLength() const
376 : {
377 41919127 : JS_ASSERT(isArray());
378 41919127 : return getElementsHeader()->length;
379 : }
380 :
381 : inline void
382 3410042 : JSObject::setArrayLength(JSContext *cx, uint32_t length)
383 : {
384 3410042 : JS_ASSERT(isArray());
385 :
386 3410042 : if (length > INT32_MAX) {
387 : /*
388 : * Mark the type of this object as possibly not a dense array, per the
389 : * requirements of OBJECT_FLAG_NON_DENSE_ARRAY.
390 : */
391 : js::types::MarkTypeObjectFlags(cx, this,
392 : js::types::OBJECT_FLAG_NON_PACKED_ARRAY |
393 36 : js::types::OBJECT_FLAG_NON_DENSE_ARRAY);
394 36 : jsid lengthId = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
395 : js::types::AddTypePropertyId(cx, this, lengthId,
396 36 : js::types::Type::DoubleType());
397 : }
398 :
399 3410042 : getElementsHeader()->length = length;
400 3410042 : }
401 :
402 : inline void
403 6105891 : JSObject::setDenseArrayLength(uint32_t length)
404 : {
405 : /* Variant of setArrayLength for use on dense arrays where the length cannot overflow int32. */
406 6105891 : JS_ASSERT(isDenseArray());
407 6105891 : JS_ASSERT(length <= INT32_MAX);
408 6105891 : getElementsHeader()->length = length;
409 6105891 : }
410 :
411 : inline void
412 558739 : JSObject::setDenseArrayInitializedLength(uint32_t length)
413 : {
414 558739 : JS_ASSERT(isDenseArray());
415 558739 : JS_ASSERT(length <= getDenseArrayCapacity());
416 558739 : prepareElementRangeForOverwrite(length, getElementsHeader()->initializedLength);
417 558739 : getElementsHeader()->initializedLength = length;
418 558739 : }
419 :
420 : inline uint32_t
421 31303295 : JSObject::getDenseArrayCapacity()
422 : {
423 31303295 : JS_ASSERT(isDenseArray());
424 31303295 : return getElementsHeader()->capacity;
425 : }
426 :
427 : inline bool
428 2593552 : JSObject::ensureElements(JSContext *cx, uint32_t capacity)
429 : {
430 2593552 : if (capacity > getDenseArrayCapacity())
431 24751 : return growElements(cx, capacity);
432 2568801 : return true;
433 : }
434 :
435 : inline void
436 23073278 : JSObject::setDenseArrayElement(unsigned idx, const js::Value &val)
437 : {
438 23073278 : JS_ASSERT(isDenseArray() && idx < getDenseArrayInitializedLength());
439 23073278 : elements[idx].set(this, idx, val);
440 23073278 : }
441 :
442 : inline void
443 487065 : JSObject::initDenseArrayElement(unsigned idx, const js::Value &val)
444 : {
445 487065 : JS_ASSERT(isDenseArray() && idx < getDenseArrayInitializedLength());
446 487065 : elements[idx].init(this, idx, val);
447 487065 : }
448 :
449 : inline void
450 23025481 : JSObject::setDenseArrayElementWithType(JSContext *cx, unsigned idx, const js::Value &val)
451 : {
452 23025481 : js::types::AddTypePropertyId(cx, this, JSID_VOID, val);
453 23025481 : setDenseArrayElement(idx, val);
454 23025481 : }
455 :
456 : inline void
457 487065 : JSObject::initDenseArrayElementWithType(JSContext *cx, unsigned idx, const js::Value &val)
458 : {
459 487065 : js::types::AddTypePropertyId(cx, this, JSID_VOID, val);
460 487065 : initDenseArrayElement(idx, val);
461 487065 : }
462 :
463 : inline void
464 42995 : JSObject::copyDenseArrayElements(unsigned dstStart, const js::Value *src, unsigned count)
465 : {
466 42995 : JS_ASSERT(dstStart + count <= getDenseArrayCapacity());
467 42995 : JSCompartment *comp = compartment();
468 181196 : for (unsigned i = 0; i < count; ++i)
469 138201 : elements[dstStart + i].set(comp, this, dstStart + i, src[i]);
470 42995 : }
471 :
472 : inline void
473 43384 : JSObject::initDenseArrayElements(unsigned dstStart, const js::Value *src, unsigned count)
474 : {
475 43384 : JS_ASSERT(dstStart + count <= getDenseArrayCapacity());
476 43384 : JSCompartment *comp = compartment();
477 345103 : for (unsigned i = 0; i < count; ++i)
478 301719 : elements[dstStart + i].init(comp, this, dstStart + i, src[i]);
479 43384 : }
480 :
481 : inline void
482 1386 : JSObject::moveDenseArrayElements(unsigned dstStart, unsigned srcStart, unsigned count)
483 : {
484 1386 : JS_ASSERT(dstStart + count <= getDenseArrayCapacity());
485 1386 : JS_ASSERT(srcStart + count <= getDenseArrayInitializedLength());
486 :
487 : /*
488 : * Using memmove here would skip write barriers. Also, we need to consider
489 : * an array containing [A, B, C], in the following situation:
490 : *
491 : * 1. Incremental GC marks slot 0 of array (i.e., A), then returns to JS code.
492 : * 2. JS code moves slots 1..2 into slots 0..1, so it contains [B, C, C].
493 : * 3. Incremental GC finishes by marking slots 1 and 2 (i.e., C).
494 : *
495 : * Since normal marking never happens on B, it is very important that the
496 : * write barrier is invoked here on B, despite the fact that it exists in
497 : * the array before and after the move.
498 : */
499 1386 : JSCompartment *comp = compartment();
500 1386 : if (comp->needsBarrier()) {
501 23 : if (dstStart < srcStart) {
502 23 : js::HeapSlot *dst = elements + dstStart;
503 23 : js::HeapSlot *src = elements + srcStart;
504 30 : for (unsigned i = 0; i < count; i++, dst++, src++)
505 7 : dst->set(comp, this, dst - elements, *src);
506 : } else {
507 0 : js::HeapSlot *dst = elements + dstStart + count - 1;
508 0 : js::HeapSlot *src = elements + srcStart + count - 1;
509 0 : for (unsigned i = 0; i < count; i++, dst--, src--)
510 0 : dst->set(comp, this, dst - elements, *src);
511 : }
512 : } else {
513 1363 : memmove(elements + dstStart, elements + srcStart, count * sizeof(js::HeapSlot));
514 1363 : SlotRangeWriteBarrierPost(comp, this, dstStart, count);
515 : }
516 1386 : }
517 :
518 : inline void
519 66 : JSObject::moveDenseArrayElementsUnbarriered(unsigned dstStart, unsigned srcStart, unsigned count)
520 : {
521 66 : JS_ASSERT(!compartment()->needsBarrier());
522 :
523 66 : JS_ASSERT(dstStart + count <= getDenseArrayCapacity());
524 66 : JS_ASSERT(srcStart + count <= getDenseArrayCapacity());
525 :
526 66 : memmove(elements + dstStart, elements + srcStart, count * sizeof(js::Value));
527 66 : }
528 :
529 : inline bool
530 : JSObject::denseArrayHasInlineSlots() const
531 : {
532 : JS_ASSERT(isDenseArray());
533 : return elements == fixedElements();
534 : }
535 :
536 : namespace js {
537 :
538 : /*
539 : * Any name atom for a function which will be added as a DeclEnv object to the
540 : * scope chain above call objects for fun.
541 : */
542 : static inline JSAtom *
543 782484 : CallObjectLambdaName(JSFunction *fun)
544 : {
545 782484 : return (fun->flags & JSFUN_LAMBDA) ? fun->atom.get() : NULL;
546 : }
547 :
548 : } /* namespace js */
549 :
550 : inline const js::Value &
551 91305 : JSObject::getDateUTCTime() const
552 : {
553 91305 : JS_ASSERT(isDate());
554 91305 : return getFixedSlot(JSSLOT_DATE_UTC_TIME);
555 : }
556 :
557 : inline void
558 52158 : JSObject::setDateUTCTime(const js::Value &time)
559 : {
560 52158 : JS_ASSERT(isDate());
561 52158 : setFixedSlot(JSSLOT_DATE_UTC_TIME, time);
562 52158 : }
563 :
564 : inline js::NativeIterator *
565 31206563 : JSObject::getNativeIterator() const
566 : {
567 31206563 : return (js::NativeIterator *) getPrivate();
568 : }
569 :
570 : inline void
571 397137 : JSObject::setNativeIterator(js::NativeIterator *ni)
572 : {
573 397137 : setPrivate(ni);
574 397137 : }
575 :
576 : inline JSLinearString *
577 4732751 : JSObject::getNamePrefix() const
578 : {
579 4732751 : JS_ASSERT(isNamespace() || isQName());
580 4732751 : const js::Value &v = getSlot(JSSLOT_NAME_PREFIX);
581 4732751 : return !v.isUndefined() ? &v.toString()->asLinear() : NULL;
582 : }
583 :
584 : inline jsval
585 4735284 : JSObject::getNamePrefixVal() const
586 : {
587 4735284 : JS_ASSERT(isNamespace() || isQName());
588 4735284 : return getSlot(JSSLOT_NAME_PREFIX);
589 : }
590 :
591 : inline void
592 4735783 : JSObject::setNamePrefix(JSLinearString *prefix)
593 : {
594 4735783 : JS_ASSERT(isNamespace() || isQName());
595 4735783 : setSlot(JSSLOT_NAME_PREFIX, prefix ? js::StringValue(prefix) : js::UndefinedValue());
596 4735783 : }
597 :
598 : inline void
599 0 : JSObject::clearNamePrefix()
600 : {
601 0 : JS_ASSERT(isNamespace() || isQName());
602 0 : setSlot(JSSLOT_NAME_PREFIX, js::UndefinedValue());
603 0 : }
604 :
605 : inline JSLinearString *
606 4746261 : JSObject::getNameURI() const
607 : {
608 4746261 : JS_ASSERT(isNamespace() || isQName());
609 4746261 : const js::Value &v = getSlot(JSSLOT_NAME_URI);
610 4746261 : return !v.isUndefined() ? &v.toString()->asLinear() : NULL;
611 : }
612 :
613 : inline jsval
614 4735284 : JSObject::getNameURIVal() const
615 : {
616 4735284 : JS_ASSERT(isNamespace() || isQName());
617 4735284 : return getSlot(JSSLOT_NAME_URI);
618 : }
619 :
620 : inline void
621 4735810 : JSObject::setNameURI(JSLinearString *uri)
622 : {
623 4735810 : JS_ASSERT(isNamespace() || isQName());
624 4735810 : setSlot(JSSLOT_NAME_URI, uri ? js::StringValue(uri) : js::UndefinedValue());
625 4735810 : }
626 :
627 : inline jsval
628 4720258 : JSObject::getNamespaceDeclared() const
629 : {
630 4720258 : JS_ASSERT(isNamespace());
631 4720258 : return getSlot(JSSLOT_NAMESPACE_DECLARED);
632 : }
633 :
634 : inline void
635 2009 : JSObject::setNamespaceDeclared(jsval decl)
636 : {
637 2009 : JS_ASSERT(isNamespace());
638 2009 : setSlot(JSSLOT_NAMESPACE_DECLARED, decl);
639 2009 : }
640 :
641 : inline JSAtom *
642 2362923 : JSObject::getQNameLocalName() const
643 : {
644 2362923 : JS_ASSERT(isQName());
645 2362923 : const js::Value &v = getSlot(JSSLOT_QNAME_LOCAL_NAME);
646 2362923 : return !v.isUndefined() ? &v.toString()->asAtom() : NULL;
647 : }
648 :
649 : inline jsval
650 2374457 : JSObject::getQNameLocalNameVal() const
651 : {
652 2374457 : JS_ASSERT(isQName());
653 2374457 : return getSlot(JSSLOT_QNAME_LOCAL_NAME);
654 : }
655 :
656 : inline void
657 2374457 : JSObject::setQNameLocalName(JSAtom *name)
658 : {
659 2374457 : JS_ASSERT(isQName());
660 2374457 : setSlot(JSSLOT_QNAME_LOCAL_NAME, name ? js::StringValue(name) : js::UndefinedValue());
661 2374457 : }
662 :
663 : inline bool
664 7343372 : JSObject::setSingletonType(JSContext *cx)
665 : {
666 7343372 : if (!cx->typeInferenceEnabled())
667 3262284 : return true;
668 :
669 4081088 : JS_ASSERT(!hasLazyType());
670 4081088 : JS_ASSERT_IF(getProto(), type() == getProto()->getNewType(cx, NULL));
671 :
672 4081088 : js::types::TypeObject *type = cx->compartment->getLazyType(cx, getProto());
673 4081088 : if (!type)
674 0 : return false;
675 :
676 4081088 : type_ = type;
677 4081088 : return true;
678 : }
679 :
680 : inline js::types::TypeObject *
681 1234446 : JSObject::getType(JSContext *cx)
682 : {
683 1234446 : if (hasLazyType())
684 51868 : makeLazyType(cx);
685 1234446 : return type_;
686 : }
687 :
688 : inline bool
689 3003 : JSObject::clearType(JSContext *cx)
690 : {
691 3003 : JS_ASSERT(!hasSingletonType());
692 :
693 3003 : js::types::TypeObject *type = cx->compartment->getEmptyType(cx);
694 3003 : if (!type)
695 0 : return false;
696 :
697 3003 : type_ = type;
698 3003 : return true;
699 : }
700 :
701 : inline void
702 4806628 : JSObject::setType(js::types::TypeObject *newType)
703 : {
704 : #ifdef DEBUG
705 4806628 : JS_ASSERT(newType);
706 12351999 : for (JSObject *obj = newType->proto; obj; obj = obj->getProto())
707 7545371 : JS_ASSERT(obj != this);
708 : #endif
709 4806628 : JS_ASSERT_IF(hasSpecialEquality(),
710 4806628 : newType->hasAnyFlags(js::types::OBJECT_FLAG_SPECIAL_EQUALITY));
711 4806628 : JS_ASSERT(!hasSingletonType());
712 4806628 : type_ = newType;
713 4806628 : }
714 :
715 80355 : inline bool JSObject::setIteratedSingleton(JSContext *cx)
716 : {
717 80355 : return setFlag(cx, js::BaseShape::ITERATED_SINGLETON);
718 : }
719 :
720 0 : inline bool JSObject::isSystem() const
721 : {
722 0 : return lastProperty()->hasObjectFlag(js::BaseShape::SYSTEM);
723 : }
724 :
725 0 : inline bool JSObject::setSystem(JSContext *cx)
726 : {
727 0 : return setFlag(cx, js::BaseShape::SYSTEM);
728 : }
729 :
730 1022851 : inline bool JSObject::setDelegate(JSContext *cx)
731 : {
732 1022851 : return setFlag(cx, js::BaseShape::DELEGATE, GENERATE_SHAPE);
733 : }
734 :
735 201842 : inline bool JSObject::isVarObj() const
736 : {
737 201842 : return lastProperty()->hasObjectFlag(js::BaseShape::VAROBJ);
738 : }
739 :
740 81043 : inline bool JSObject::setVarObj(JSContext *cx)
741 : {
742 81043 : return setFlag(cx, js::BaseShape::VAROBJ);
743 : }
744 :
745 3672 : inline bool JSObject::setWatched(JSContext *cx)
746 : {
747 3672 : return setFlag(cx, js::BaseShape::WATCHED, GENERATE_SHAPE);
748 : }
749 :
750 812081 : inline bool JSObject::hasUncacheableProto() const
751 : {
752 812081 : return lastProperty()->hasObjectFlag(js::BaseShape::UNCACHEABLE_PROTO);
753 : }
754 :
755 31940 : inline bool JSObject::setUncacheableProto(JSContext *cx)
756 : {
757 31940 : return setFlag(cx, js::BaseShape::UNCACHEABLE_PROTO, GENERATE_SHAPE);
758 : }
759 :
760 1786707 : inline bool JSObject::isBoundFunction() const
761 : {
762 1786707 : return lastProperty()->hasObjectFlag(js::BaseShape::BOUND_FUNCTION);
763 : }
764 :
765 4009507 : inline bool JSObject::isIndexed() const
766 : {
767 4009507 : return lastProperty()->hasObjectFlag(js::BaseShape::INDEXED);
768 : }
769 :
770 4656027 : inline bool JSObject::watched() const
771 : {
772 4656027 : return lastProperty()->hasObjectFlag(js::BaseShape::WATCHED);
773 : }
774 :
775 4919641 : inline bool JSObject::hasSpecialEquality() const
776 : {
777 4919641 : return !!getClass()->ext.equality;
778 : }
779 :
780 23117301 : inline bool JSObject::isArguments() const { return isNormalArguments() || isStrictArguments(); }
781 20627 : inline bool JSObject::isArrayBuffer() const { return hasClass(&js::ArrayBufferClass); }
782 31128734 : inline bool JSObject::isBlock() const { return hasClass(&js::BlockClass); }
783 6955 : inline bool JSObject::isBoolean() const { return hasClass(&js::BooleanClass); }
784 29586770 : inline bool JSObject::isCall() const { return hasClass(&js::CallClass); }
785 8717 : inline bool JSObject::isClonedBlock() const { return isBlock() && !!getProto(); }
786 760155 : inline bool JSObject::isDate() const { return hasClass(&js::DateClass); }
787 10472065 : inline bool JSObject::isDeclEnv() const { return hasClass(&js::DeclEnvClass); }
788 25151 : inline bool JSObject::isElementIterator() const { return hasClass(&js::ElementIteratorClass); }
789 113459 : inline bool JSObject::isError() const { return hasClass(&js::ErrorClass); }
790 207372408 : inline bool JSObject::isFunction() const { return hasClass(&js::FunctionClass); }
791 : inline bool JSObject::isFunctionProxy() const { return hasClass(&js::FunctionProxyClass); }
792 7510 : inline bool JSObject::isGenerator() const { return hasClass(&js::GeneratorClass); }
793 31192408 : inline bool JSObject::isIterator() const { return hasClass(&js::IteratorClass); }
794 33143440 : inline bool JSObject::isNamespace() const { return hasClass(&js::NamespaceClass); }
795 10156139 : inline bool JSObject::isNestedScope() const { return isBlock() || isWith(); }
796 23491953 : inline bool JSObject::isNormalArguments() const { return hasClass(&js::NormalArgumentsObjectClass); }
797 160596 : inline bool JSObject::isNumber() const { return hasClass(&js::NumberClass); }
798 2077309 : inline bool JSObject::isObject() const { return hasClass(&js::ObjectClass); }
799 : inline bool JSObject::isPrimitive() const { return isNumber() || isString() || isBoolean(); }
800 3491324 : inline bool JSObject::isRegExp() const { return hasClass(&js::RegExpClass); }
801 : inline bool JSObject::isRegExpStatics() const { return hasClass(&js::RegExpStaticsClass); }
802 15894602 : inline bool JSObject::isScope() const { return isCall() || isDeclEnv() || isNestedScope(); }
803 3175370 : inline bool JSObject::isStaticBlock() const { return isBlock() && !getProto(); }
804 197561 : inline bool JSObject::isStopIteration() const { return hasClass(&js::StopIterationClass); }
805 21761582 : inline bool JSObject::isStrictArguments() const { return hasClass(&js::StrictArgumentsObjectClass); }
806 1259051 : inline bool JSObject::isString() const { return hasClass(&js::StringClass); }
807 0 : inline bool JSObject::isTypedArray() const { return IsFastTypedArrayClass(getClass()); }
808 1463 : inline bool JSObject::isWeakMap() const { return hasClass(&js::WeakMapClass); }
809 27346180 : inline bool JSObject::isWith() const { return hasClass(&js::WithClass); }
810 6161199 : inline bool JSObject::isXML() const { return hasClass(&js::XMLClass); }
811 :
812 : inline bool
813 72 : JSObject::isXMLId() const
814 : {
815 72 : return hasClass(&js::QNameClass)
816 36 : || hasClass(&js::AttributeNameClass)
817 108 : || hasClass(&js::AnyNameClass);
818 : }
819 :
820 : inline bool
821 23715503 : JSObject::isQName() const
822 : {
823 23715503 : return hasClass(&js::QNameClass)
824 1179 : || hasClass(&js::AttributeNameClass)
825 23716682 : || hasClass(&js::AnyNameClass);
826 : }
827 :
828 : /* static */ inline JSObject *
829 6560997 : JSObject::create(JSContext *cx, js::gc::AllocKind kind,
830 : js::HandleShape shape, js::HandleTypeObject type, js::HeapSlot *slots)
831 : {
832 : /*
833 : * Callers must use dynamicSlotsCount to size the initial slot array of the
834 : * object. We can't check the allocated capacity of the dynamic slots, but
835 : * make sure their presence is consistent with the shape.
836 : */
837 6560997 : JS_ASSERT(shape && type);
838 6560997 : JS_ASSERT(!!dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan()) == !!slots);
839 6560997 : JS_ASSERT(js::gc::GetGCKindSlots(kind, shape->getObjectClass()) == shape->numFixedSlots());
840 :
841 6560997 : JSObject *obj = js_NewGCObject(cx, kind);
842 6560997 : if (!obj)
843 0 : return NULL;
844 :
845 6560997 : obj->shape_.init(shape);
846 6560997 : obj->type_.init(type);
847 6560997 : obj->slots = slots;
848 6560997 : obj->elements = js::emptyObjectElements;
849 :
850 6560997 : if (shape->getObjectClass()->hasPrivate())
851 1572307 : obj->privateRef(shape->numFixedSlots()) = NULL;
852 :
853 6560997 : if (size_t span = shape->slotSpan())
854 1620839 : obj->initializeSlotRange(0, span);
855 :
856 6560997 : return obj;
857 : }
858 :
859 : /* static */ inline JSObject *
860 220517 : JSObject::createDenseArray(JSContext *cx, js::gc::AllocKind kind,
861 : js::HandleShape shape, js::HandleTypeObject type,
862 : uint32_t length)
863 : {
864 220517 : JS_ASSERT(shape && type);
865 220517 : JS_ASSERT(shape->getObjectClass() == &js::ArrayClass);
866 :
867 : /*
868 : * Dense arrays are non-native, and never have properties to store.
869 : * The number of fixed slots in the shape of such objects is zero.
870 : */
871 220517 : JS_ASSERT(shape->numFixedSlots() == 0);
872 :
873 : /*
874 : * The array initially stores its elements inline, there must be enough
875 : * space for an elements header.
876 : */
877 220517 : JS_ASSERT(js::gc::GetGCKindSlots(kind) >= js::ObjectElements::VALUES_PER_HEADER);
878 :
879 220517 : uint32_t capacity = js::gc::GetGCKindSlots(kind) - js::ObjectElements::VALUES_PER_HEADER;
880 :
881 220517 : JSObject *obj = js_NewGCObject(cx, kind);
882 220517 : if (!obj) {
883 0 : js_ReportOutOfMemory(cx);
884 0 : return NULL;
885 : }
886 :
887 220517 : obj->shape_.init(shape);
888 220517 : obj->type_.init(type);
889 220517 : obj->slots = NULL;
890 220517 : obj->setFixedElements();
891 220517 : new (obj->getElementsHeader()) js::ObjectElements(capacity, length);
892 :
893 220517 : return obj;
894 : }
895 :
896 : inline void
897 30978300 : JSObject::finish(js::FreeOp *fop)
898 : {
899 30978300 : if (hasDynamicSlots())
900 4039887 : fop->free_(slots);
901 30978300 : if (hasDynamicElements())
902 274298 : fop->free_(getElementsHeader());
903 30978300 : }
904 :
905 : inline bool
906 3099479 : JSObject::hasProperty(JSContext *cx, jsid id, bool *foundp, unsigned flags)
907 : {
908 : JSObject *pobj;
909 : JSProperty *prop;
910 6198958 : JSAutoResolveFlags rf(cx, flags);
911 3099479 : if (!lookupGeneric(cx, id, &pobj, &prop))
912 0 : return false;
913 3099479 : *foundp = !!prop;
914 3099479 : return true;
915 : }
916 :
917 : inline bool
918 2088610 : JSObject::isCallable()
919 : {
920 2088610 : return isFunction() || getClass()->call;
921 : }
922 :
923 : inline JSPrincipals *
924 106377 : JSObject::principals(JSContext *cx)
925 : {
926 106377 : if (JSObjectPrincipalsFinder find = cx->runtime->securityCallbacks->findObjectPrincipals)
927 25 : return find(this);
928 106352 : return cx->compartment ? cx->compartment->principals : NULL;
929 : }
930 :
931 : inline void
932 38356032 : JSObject::nativeSetSlot(unsigned slot, const js::Value &value)
933 : {
934 38356032 : JS_ASSERT(isNative());
935 38356032 : JS_ASSERT(slot < slotSpan());
936 38356032 : return setSlot(slot, value);
937 : }
938 :
939 : inline void
940 14750119 : JSObject::nativeSetSlotWithType(JSContext *cx, const js::Shape *shape, const js::Value &value)
941 : {
942 14750119 : nativeSetSlot(shape->slot(), value);
943 14750119 : js::types::AddTypePropertyId(cx, this, shape->propid(), value);
944 14750119 : }
945 :
946 : inline bool
947 146111 : JSObject::nativeContains(JSContext *cx, jsid id)
948 : {
949 146111 : return nativeLookup(cx, id) != NULL;
950 : }
951 :
952 : inline bool
953 17331637 : JSObject::nativeContains(JSContext *cx, const js::Shape &shape)
954 : {
955 17331637 : return nativeLookup(cx, shape.propid()) == &shape;
956 : }
957 :
958 : inline bool
959 3012027 : JSObject::nativeEmpty() const
960 : {
961 3012027 : return lastProperty()->isEmptyShape();
962 : }
963 :
964 : inline uint32_t
965 1590457 : JSObject::propertyCount() const
966 : {
967 1590457 : return lastProperty()->entryCount();
968 : }
969 :
970 : inline bool
971 0 : JSObject::hasPropertyTable() const
972 : {
973 0 : return lastProperty()->hasTable();
974 : }
975 :
976 : inline size_t
977 0 : JSObject::computedSizeOfThisSlotsElements() const
978 : {
979 0 : size_t n = sizeOfThis();
980 :
981 0 : if (hasDynamicSlots())
982 0 : n += numDynamicSlots() * sizeof(js::Value);
983 :
984 0 : if (hasDynamicElements())
985 0 : n += (js::ObjectElements::VALUES_PER_HEADER + getElementsHeader()->capacity) *
986 0 : sizeof(js::Value);
987 :
988 0 : return n;
989 : }
990 :
991 : inline void
992 : JSObject::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf,
993 : size_t *slotsSize, size_t *elementsSize,
994 : size_t *miscSize) const
995 : {
996 : *slotsSize = 0;
997 : if (hasDynamicSlots()) {
998 : *slotsSize += mallocSizeOf(slots);
999 : }
1000 :
1001 : *elementsSize = 0;
1002 : if (hasDynamicElements()) {
1003 : *elementsSize += mallocSizeOf(getElementsHeader());
1004 : }
1005 :
1006 : /* Other things may be measured in the future if DMD indicates it is worthwhile. */
1007 : *miscSize = 0;
1008 : if (isArguments()) {
1009 : *miscSize += asArguments().sizeOfMisc(mallocSizeOf);
1010 : } else if (isRegExpStatics()) {
1011 : *miscSize += js::SizeOfRegExpStaticsData(this, mallocSizeOf);
1012 : }
1013 : }
1014 :
1015 : inline JSBool
1016 5645865 : JSObject::lookupGeneric(JSContext *cx, jsid id, JSObject **objp, JSProperty **propp)
1017 : {
1018 5645865 : js::LookupGenericOp op = getOps()->lookupGeneric;
1019 5645865 : return (op ? op : js_LookupProperty)(cx, this, id, objp, propp);
1020 : }
1021 :
1022 : inline JSBool
1023 169734 : JSObject::lookupProperty(JSContext *cx, js::PropertyName *name, JSObject **objp, JSProperty **propp)
1024 : {
1025 169734 : return lookupGeneric(cx, ATOM_TO_JSID(name), objp, propp);
1026 : }
1027 :
1028 : inline JSBool
1029 18826122 : JSObject::defineGeneric(JSContext *cx, jsid id, const js::Value &value,
1030 : JSPropertyOp getter /* = JS_PropertyStub */,
1031 : JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
1032 : unsigned attrs /* = JSPROP_ENUMERATE */)
1033 : {
1034 18826122 : JS_ASSERT(!(attrs & JSPROP_NATIVE_ACCESSORS));
1035 18826122 : js::DefineGenericOp op = getOps()->defineGeneric;
1036 18826122 : return (op ? op : js_DefineProperty)(cx, this, id, &value, getter, setter, attrs);
1037 : }
1038 :
1039 : inline JSBool
1040 1267885 : JSObject::defineProperty(JSContext *cx, js::PropertyName *name, const js::Value &value,
1041 : JSPropertyOp getter /* = JS_PropertyStub */,
1042 : JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
1043 : unsigned attrs /* = JSPROP_ENUMERATE */)
1044 : {
1045 1267885 : return defineGeneric(cx, ATOM_TO_JSID(name), value, getter, setter, attrs);
1046 : }
1047 :
1048 : inline JSBool
1049 8359 : JSObject::defineElement(JSContext *cx, uint32_t index, const js::Value &value,
1050 : JSPropertyOp getter /* = JS_PropertyStub */,
1051 : JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
1052 : unsigned attrs /* = JSPROP_ENUMERATE */)
1053 : {
1054 8359 : js::DefineElementOp op = getOps()->defineElement;
1055 8359 : return (op ? op : js_DefineElement)(cx, this, index, &value, getter, setter, attrs);
1056 : }
1057 :
1058 : inline JSBool
1059 325 : JSObject::defineSpecial(JSContext *cx, js::SpecialId sid, const js::Value &value,
1060 : JSPropertyOp getter /* = JS_PropertyStub */,
1061 : JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
1062 : unsigned attrs /* = JSPROP_ENUMERATE */)
1063 : {
1064 325 : return defineGeneric(cx, SPECIALID_TO_JSID(sid), value, getter, setter, attrs);
1065 : }
1066 :
1067 : inline JSBool
1068 0 : JSObject::lookupElement(JSContext *cx, uint32_t index, JSObject **objp, JSProperty **propp)
1069 : {
1070 0 : js::LookupElementOp op = getOps()->lookupElement;
1071 0 : return (op ? op : js_LookupElement)(cx, this, index, objp, propp);
1072 : }
1073 :
1074 : inline JSBool
1075 : JSObject::lookupSpecial(JSContext *cx, js::SpecialId sid, JSObject **objp, JSProperty **propp)
1076 : {
1077 : return lookupGeneric(cx, SPECIALID_TO_JSID(sid), objp, propp);
1078 : }
1079 :
1080 : inline JSBool
1081 1637345 : JSObject::getElement(JSContext *cx, JSObject *receiver, uint32_t index, js::Value *vp)
1082 : {
1083 1637345 : js::ElementIdOp op = getOps()->getElement;
1084 1637345 : if (op)
1085 700755 : return op(cx, this, receiver, index, vp);
1086 :
1087 : jsid id;
1088 936590 : if (!js::IndexToId(cx, index, &id))
1089 0 : return false;
1090 936590 : return getGeneric(cx, receiver, id, vp);
1091 : }
1092 :
1093 : inline JSBool
1094 1134831 : JSObject::getElement(JSContext *cx, uint32_t index, js::Value *vp)
1095 : {
1096 1134831 : return getElement(cx, this, index, vp);
1097 : }
1098 :
1099 : inline JSBool
1100 505294 : JSObject::getElementIfPresent(JSContext *cx, JSObject *receiver, uint32_t index, js::Value *vp,
1101 : bool *present)
1102 : {
1103 505294 : js::ElementIfPresentOp op = getOps()->getElementIfPresent;
1104 505294 : if (op)
1105 513 : return op(cx, this, receiver, index, vp, present);
1106 :
1107 : /* For now, do the index-to-id conversion just once, then use
1108 : * lookupGeneric/getGeneric. Once lookupElement and getElement stop both
1109 : * doing index-to-id conversions, we can use those here.
1110 : */
1111 : jsid id;
1112 504781 : if (!js::IndexToId(cx, index, &id))
1113 0 : return false;
1114 :
1115 : JSObject *obj2;
1116 : JSProperty *prop;
1117 504781 : if (!lookupGeneric(cx, id, &obj2, &prop))
1118 0 : return false;
1119 :
1120 504781 : if (!prop) {
1121 503134 : *present = false;
1122 503134 : js::Debug_SetValueRangeToCrashOnTouch(vp, 1);
1123 503134 : return true;
1124 : }
1125 :
1126 1647 : *present = true;
1127 1647 : return getGeneric(cx, receiver, id, vp);
1128 : }
1129 :
1130 : inline JSBool
1131 13267 : JSObject::getSpecial(JSContext *cx, JSObject *receiver, js::SpecialId sid, js::Value *vp)
1132 : {
1133 13267 : return getGeneric(cx, receiver, SPECIALID_TO_JSID(sid), vp);
1134 : }
1135 :
1136 : inline JSBool
1137 83259 : JSObject::getGenericAttributes(JSContext *cx, jsid id, unsigned *attrsp)
1138 : {
1139 83259 : js::GenericAttributesOp op = getOps()->getGenericAttributes;
1140 83259 : return (op ? op : js_GetAttributes)(cx, this, id, attrsp);
1141 : }
1142 :
1143 : inline JSBool
1144 1127 : JSObject::getPropertyAttributes(JSContext *cx, js::PropertyName *name, unsigned *attrsp)
1145 : {
1146 1127 : return getGenericAttributes(cx, ATOM_TO_JSID(name), attrsp);
1147 : }
1148 :
1149 : inline JSBool
1150 0 : JSObject::getElementAttributes(JSContext *cx, uint32_t index, unsigned *attrsp)
1151 : {
1152 : jsid id;
1153 0 : if (!js::IndexToId(cx, index, &id))
1154 0 : return false;
1155 0 : return getGenericAttributes(cx, id, attrsp);
1156 : }
1157 :
1158 : inline JSBool
1159 0 : JSObject::getSpecialAttributes(JSContext *cx, js::SpecialId sid, unsigned *attrsp)
1160 : {
1161 0 : return getGenericAttributes(cx, SPECIALID_TO_JSID(sid), attrsp);
1162 : }
1163 :
1164 : inline bool
1165 49848464 : JSObject::isProxy() const
1166 : {
1167 49848464 : return js::IsProxy(this);
1168 : }
1169 :
1170 : inline bool
1171 66044 : JSObject::isCrossCompartmentWrapper() const
1172 : {
1173 66044 : return js::IsCrossCompartmentWrapper(this);
1174 : }
1175 :
1176 : inline bool
1177 59282117 : JSObject::isWrapper() const
1178 : {
1179 59282117 : return js::IsWrapper(this);
1180 : }
1181 :
1182 : inline js::GlobalObject &
1183 998848527 : JSObject::global() const
1184 : {
1185 998848527 : JSObject *obj = const_cast<JSObject *>(this);
1186 1059866463 : while (JSObject *parent = obj->getParent())
1187 30508968 : obj = parent;
1188 998848527 : return obj->asGlobal();
1189 : }
1190 :
1191 : static inline bool
1192 2372375 : js_IsCallable(const js::Value &v)
1193 : {
1194 2372375 : return v.isObject() && v.toObject().isCallable();
1195 : }
1196 :
1197 : namespace js {
1198 :
1199 : inline void
1200 512198 : OBJ_TO_INNER_OBJECT(JSContext *cx, JSObject *&obj)
1201 : {
1202 512198 : if (JSObjectOp op = obj->getClass()->ext.innerObject)
1203 0 : obj = op(cx, obj);
1204 512198 : }
1205 :
1206 : inline void
1207 97865 : OBJ_TO_OUTER_OBJECT(JSContext *cx, JSObject *&obj)
1208 : {
1209 97865 : if (JSObjectOp op = obj->getClass()->ext.outerObject)
1210 0 : obj = op(cx, obj);
1211 97865 : }
1212 :
1213 : /*
1214 : * Methods to test whether an object or a value is of type "xml" (per typeof).
1215 : */
1216 :
1217 : #define VALUE_IS_XML(v) (!JSVAL_IS_PRIMITIVE(v) && JSVAL_TO_OBJECT(v)->isXML())
1218 :
1219 : static inline bool
1220 9602804 : IsXML(const js::Value &v)
1221 : {
1222 9602804 : return v.isObject() && v.toObject().isXML();
1223 : }
1224 :
1225 : static inline bool
1226 3362 : IsStopIteration(const js::Value &v)
1227 : {
1228 3362 : return v.isObject() && v.toObject().isStopIteration();
1229 : }
1230 :
1231 : /* ES5 9.1 ToPrimitive(input). */
1232 : static JS_ALWAYS_INLINE bool
1233 25267777 : ToPrimitive(JSContext *cx, Value *vp)
1234 : {
1235 25267777 : if (vp->isPrimitive())
1236 24735260 : return true;
1237 532517 : return vp->toObject().defaultValue(cx, JSTYPE_VOID, vp);
1238 : }
1239 :
1240 : /* ES5 9.1 ToPrimitive(input, PreferredType). */
1241 : static JS_ALWAYS_INLINE bool
1242 10576798 : ToPrimitive(JSContext *cx, JSType preferredType, Value *vp)
1243 : {
1244 10576798 : JS_ASSERT(preferredType != JSTYPE_VOID); /* Use the other ToPrimitive! */
1245 10576798 : if (vp->isPrimitive())
1246 10216680 : return true;
1247 360118 : return vp->toObject().defaultValue(cx, preferredType, vp);
1248 : }
1249 :
1250 : /*
1251 : * Return true if this is a compiler-created internal function accessed by
1252 : * its own object. Such a function object must not be accessible to script
1253 : * or embedding code.
1254 : */
1255 : inline bool
1256 951597 : IsInternalFunctionObject(JSObject *funobj)
1257 : {
1258 951597 : JSFunction *fun = funobj->toFunction();
1259 951597 : return (fun->flags & JSFUN_LAMBDA) && !funobj->getParent();
1260 : }
1261 :
1262 : class AutoPropDescArrayRooter : private AutoGCRooter
1263 301484 : {
1264 : public:
1265 301484 : AutoPropDescArrayRooter(JSContext *cx)
1266 301484 : : AutoGCRooter(cx, DESCRIPTORS), descriptors(cx)
1267 301484 : { }
1268 :
1269 301529 : PropDesc *append() {
1270 301529 : if (!descriptors.append(PropDesc()))
1271 0 : return NULL;
1272 301529 : return &descriptors.back();
1273 : }
1274 :
1275 549 : PropDesc& operator[](size_t i) {
1276 549 : JS_ASSERT(i < descriptors.length());
1277 549 : return descriptors[i];
1278 : }
1279 :
1280 : friend void AutoGCRooter::trace(JSTracer *trc);
1281 :
1282 : private:
1283 : PropDescArray descriptors;
1284 : };
1285 :
1286 : class AutoPropertyDescriptorRooter : private AutoGCRooter, public PropertyDescriptor
1287 14960 : {
1288 : public:
1289 14933 : AutoPropertyDescriptorRooter(JSContext *cx) : AutoGCRooter(cx, DESCRIPTOR) {
1290 14933 : obj = NULL;
1291 14933 : attrs = 0;
1292 14933 : getter = (PropertyOp) NULL;
1293 14933 : setter = (StrictPropertyOp) NULL;
1294 14933 : value.setUndefined();
1295 14933 : }
1296 :
1297 27 : AutoPropertyDescriptorRooter(JSContext *cx, PropertyDescriptor *desc)
1298 27 : : AutoGCRooter(cx, DESCRIPTOR)
1299 : {
1300 27 : obj = desc->obj;
1301 27 : attrs = desc->attrs;
1302 27 : getter = desc->getter;
1303 27 : setter = desc->setter;
1304 27 : value = desc->value;
1305 27 : }
1306 :
1307 : friend void AutoGCRooter::trace(JSTracer *trc);
1308 : };
1309 :
1310 : inline bool
1311 19896288 : NewObjectCache::lookup(Class *clasp, gc::Cell *key, gc::AllocKind kind, EntryIndex *pentry)
1312 : {
1313 19896288 : uintptr_t hash = (uintptr_t(clasp) ^ uintptr_t(key)) + kind;
1314 19896288 : *pentry = hash % js::ArrayLength(entries);
1315 :
1316 19896288 : Entry *entry = &entries[*pentry];
1317 :
1318 : /* N.B. Lookups with the same clasp/key but different kinds map to different entries. */
1319 19896288 : return (entry->clasp == clasp && entry->key == key);
1320 : }
1321 :
1322 : inline bool
1323 2090502 : NewObjectCache::lookupProto(Class *clasp, JSObject *proto, gc::AllocKind kind, EntryIndex *pentry)
1324 : {
1325 2090502 : JS_ASSERT(!proto->isGlobal());
1326 2090502 : return lookup(clasp, proto, kind, pentry);
1327 : }
1328 :
1329 : inline bool
1330 15279767 : NewObjectCache::lookupGlobal(Class *clasp, js::GlobalObject *global, gc::AllocKind kind, EntryIndex *pentry)
1331 : {
1332 15279767 : return lookup(clasp, global, kind, pentry);
1333 : }
1334 :
1335 : inline bool
1336 2526019 : NewObjectCache::lookupType(Class *clasp, js::types::TypeObject *type, gc::AllocKind kind, EntryIndex *pentry)
1337 : {
1338 2526019 : return lookup(clasp, type, kind, pentry);
1339 : }
1340 :
1341 : inline void
1342 825038 : NewObjectCache::fill(EntryIndex entry_, Class *clasp, gc::Cell *key, gc::AllocKind kind, JSObject *obj)
1343 : {
1344 825038 : JS_ASSERT(unsigned(entry_) < ArrayLength(entries));
1345 825038 : Entry *entry = &entries[entry_];
1346 :
1347 825038 : JS_ASSERT(!obj->hasDynamicSlots() && !obj->hasDynamicElements());
1348 :
1349 825038 : entry->clasp = clasp;
1350 825038 : entry->key = key;
1351 825038 : entry->kind = kind;
1352 :
1353 825038 : entry->nbytes = obj->sizeOfThis();
1354 825038 : js_memcpy(&entry->templateObject, obj, entry->nbytes);
1355 825038 : }
1356 :
1357 : inline void
1358 281973 : NewObjectCache::fillProto(EntryIndex entry, Class *clasp, JSObject *proto, gc::AllocKind kind, JSObject *obj)
1359 : {
1360 281973 : JS_ASSERT(!proto->isGlobal());
1361 281973 : JS_ASSERT(obj->getProto() == proto);
1362 281973 : return fill(entry, clasp, proto, kind, obj);
1363 : }
1364 :
1365 : inline void
1366 539777 : NewObjectCache::fillGlobal(EntryIndex entry, Class *clasp, js::GlobalObject *global, gc::AllocKind kind, JSObject *obj)
1367 : {
1368 : //JS_ASSERT(global == obj->getGlobal());
1369 539777 : return fill(entry, clasp, global, kind, obj);
1370 : }
1371 :
1372 : inline void
1373 3288 : NewObjectCache::fillType(EntryIndex entry, Class *clasp, js::types::TypeObject *type, gc::AllocKind kind, JSObject *obj)
1374 : {
1375 3288 : JS_ASSERT(obj->type() == type);
1376 3288 : return fill(entry, clasp, type, kind, obj);
1377 : }
1378 :
1379 : inline void
1380 19052049 : NewObjectCache::copyCachedToObject(JSObject *dst, JSObject *src)
1381 : {
1382 19052049 : js_memcpy(dst, src, dst->sizeOfThis());
1383 : #ifdef JSGC_GENERATIONAL
1384 : Shape::writeBarrierPost(dst->shape_, &dst->shape_);
1385 : types::TypeObject::writeBarrierPost(dst->type_, &dst->type_);
1386 : #endif
1387 19052049 : }
1388 :
1389 : inline JSObject *
1390 19052050 : NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entry_)
1391 : {
1392 19052050 : JS_ASSERT(unsigned(entry_) < ArrayLength(entries));
1393 19052050 : Entry *entry = &entries[entry_];
1394 :
1395 19052050 : JSObject *obj = js_TryNewGCObject(cx, entry->kind);
1396 19052050 : if (obj) {
1397 18808869 : copyCachedToObject(obj, &entry->templateObject);
1398 18808869 : Probes::createObject(cx, obj);
1399 18808869 : return obj;
1400 : }
1401 :
1402 : /* Copy the entry to the stack first in case it is purged by a GC. */
1403 243181 : size_t nbytes = entry->nbytes;
1404 : char stackObject[sizeof(JSObject_Slots16)];
1405 243181 : JS_ASSERT(nbytes <= sizeof(stackObject));
1406 243181 : js_memcpy(&stackObject, &entry->templateObject, nbytes);
1407 :
1408 243181 : JSObject *baseobj = (JSObject *) stackObject;
1409 486362 : RootShape shapeRoot(cx, (Shape **) baseobj->addressOfShape());
1410 486362 : RootTypeObject typeRoot(cx, (types::TypeObject **) baseobj->addressOfType());
1411 :
1412 243181 : obj = js_NewGCObject(cx, entry->kind);
1413 243181 : if (obj) {
1414 243180 : copyCachedToObject(obj, baseobj);
1415 243180 : Probes::createObject(cx, obj);
1416 243180 : return obj;
1417 : }
1418 :
1419 1 : return NULL;
1420 : }
1421 :
1422 : static inline bool
1423 24221252 : CanBeFinalizedInBackground(gc::AllocKind kind, Class *clasp)
1424 : {
1425 : #ifdef JS_THREADSAFE
1426 24221252 : JS_ASSERT(kind <= gc::FINALIZE_OBJECT_LAST);
1427 : /* If the class has no finalizer or a finalizer that is safe to call on
1428 : * a different thread, we change the finalize kind. For example,
1429 : * FINALIZE_OBJECT0 calls the finalizer on the main thread,
1430 : * FINALIZE_OBJECT0_BACKGROUND calls the finalizer on the gcHelperThread.
1431 : * IsBackgroundAllocKind is called to prevent recursively incrementing
1432 : * the finalize kind; kind may already be a background finalize kind.
1433 : */
1434 24221252 : if (!gc::IsBackgroundAllocKind(kind) && !clasp->finalize)
1435 12487056 : return true;
1436 : #endif
1437 11734196 : return false;
1438 : }
1439 :
1440 : /*
1441 : * Make an object with the specified prototype. If parent is null, it will
1442 : * default to the prototype's global if the prototype is non-null.
1443 : */
1444 : JSObject *
1445 : NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
1446 : gc::AllocKind kind);
1447 :
1448 : inline JSObject *
1449 508924 : NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent)
1450 : {
1451 508924 : gc::AllocKind kind = gc::GetGCObjectKind(clasp);
1452 508924 : return NewObjectWithGivenProto(cx, clasp, proto, parent, kind);
1453 : }
1454 :
1455 : inline JSProtoKey
1456 21839267 : GetClassProtoKey(js::Class *clasp)
1457 : {
1458 21839267 : JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
1459 21839267 : if (key != JSProto_Null)
1460 21306285 : return key;
1461 532982 : if (clasp->flags & JSCLASS_IS_ANONYMOUS)
1462 846 : return JSProto_Object;
1463 532136 : return JSProto_Null;
1464 : }
1465 :
1466 : inline bool
1467 4679669 : FindProto(JSContext *cx, js::Class *clasp, HandleObject parent, JSObject **proto)
1468 : {
1469 4679669 : JSProtoKey protoKey = GetClassProtoKey(clasp);
1470 4679669 : if (!js_GetClassPrototype(cx, parent, protoKey, proto, clasp))
1471 0 : return false;
1472 4679669 : if (!(*proto) && !js_GetClassPrototype(cx, parent, JSProto_Object, proto))
1473 0 : return false;
1474 4679669 : return true;
1475 : }
1476 :
1477 : /*
1478 : * Make an object with the prototype set according to the specified prototype or class:
1479 : *
1480 : * if proto is non-null:
1481 : * use the specified proto
1482 : * for a built-in class:
1483 : * use the memoized original value of the class constructor .prototype
1484 : * property object
1485 : * else if available
1486 : * the current value of .prototype
1487 : * else
1488 : * Object.prototype.
1489 : *
1490 : * The class prototype will be fetched from the parent's global. If global is
1491 : * null, the context's active global will be used, and the resulting object's
1492 : * parent will be that global.
1493 : */
1494 : JSObject *
1495 : NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
1496 : gc::AllocKind kind);
1497 :
1498 : inline JSObject *
1499 2075669 : NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent)
1500 : {
1501 2075669 : gc::AllocKind kind = gc::GetGCObjectKind(clasp);
1502 2075669 : return NewObjectWithClassProto(cx, clasp, proto, parent, kind);
1503 : }
1504 :
1505 : /*
1506 : * Create a native instance of the given class with parent and proto set
1507 : * according to the context's active global.
1508 : */
1509 : inline JSObject *
1510 8868435 : NewBuiltinClassInstance(JSContext *cx, Class *clasp, gc::AllocKind kind)
1511 : {
1512 8868435 : return NewObjectWithClassProto(cx, clasp, NULL, NULL, kind);
1513 : }
1514 :
1515 : inline JSObject *
1516 6234114 : NewBuiltinClassInstance(JSContext *cx, Class *clasp)
1517 : {
1518 6234114 : gc::AllocKind kind = gc::GetGCObjectKind(clasp);
1519 6234114 : return NewBuiltinClassInstance(cx, clasp, kind);
1520 : }
1521 :
1522 : inline GlobalObject *
1523 11315326 : GetCurrentGlobal(JSContext *cx)
1524 : {
1525 11315326 : JSObject *scopeChain = (cx->hasfp()) ? &cx->fp()->scopeChain() : cx->globalObject;
1526 11315326 : return scopeChain ? &scopeChain->global() : NULL;
1527 : }
1528 :
1529 : bool
1530 : FindClassPrototype(JSContext *cx, JSObject *scope, JSProtoKey protoKey, JSObject **protop,
1531 : Class *clasp);
1532 :
1533 : /*
1534 : * Create a plain object with the specified type. This bypasses getNewType to
1535 : * avoid losing creation site information for objects made by scripted 'new'.
1536 : */
1537 : JSObject *
1538 : NewObjectWithType(JSContext *cx, types::TypeObject *type, JSObject *parent, gc::AllocKind kind);
1539 :
1540 : /* Make an object with pregenerated shape from a NEWOBJECT bytecode. */
1541 : static inline JSObject *
1542 2614024 : CopyInitializerObject(JSContext *cx, JSObject *baseobj)
1543 : {
1544 2614024 : JS_ASSERT(baseobj->getClass() == &ObjectClass);
1545 2614024 : JS_ASSERT(!baseobj->inDictionaryMode());
1546 :
1547 2614024 : gc::AllocKind kind = gc::GetGCObjectFixedSlotsKind(baseobj->numFixedSlots());
1548 : #ifdef JS_THREADSAFE
1549 2614024 : kind = gc::GetBackgroundAllocKind(kind);
1550 : #endif
1551 2614024 : JS_ASSERT(kind == baseobj->getAllocKind());
1552 2614024 : JSObject *obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
1553 :
1554 2614024 : if (!obj)
1555 1 : return NULL;
1556 :
1557 2614023 : if (!obj->setLastProperty(cx, baseobj->lastProperty()))
1558 0 : return NULL;
1559 :
1560 2614023 : return obj;
1561 : }
1562 :
1563 : JSObject *
1564 : NewReshapedObject(JSContext *cx, js::types::TypeObject *type, JSObject *parent,
1565 : gc::AllocKind kind, const Shape *shape);
1566 :
1567 : /*
1568 : * As for gc::GetGCObjectKind, where numSlots is a guess at the final size of
1569 : * the object, zero if the final size is unknown. This should only be used for
1570 : * objects that do not require any fixed slots.
1571 : */
1572 : static inline gc::AllocKind
1573 15211 : GuessObjectGCKind(size_t numSlots)
1574 : {
1575 15211 : if (numSlots)
1576 8443 : return gc::GetGCObjectKind(numSlots);
1577 6768 : return gc::FINALIZE_OBJECT4;
1578 : }
1579 :
1580 : static inline gc::AllocKind
1581 2266237 : GuessArrayGCKind(size_t numSlots)
1582 : {
1583 2266237 : if (numSlots)
1584 2124663 : return gc::GetGCArrayKind(numSlots);
1585 141574 : return gc::FINALIZE_OBJECT8;
1586 : }
1587 :
1588 : /*
1589 : * Get the GC kind to use for scripted 'new' on the given class.
1590 : * FIXME bug 547327: estimate the size from the allocation site.
1591 : */
1592 : static inline gc::AllocKind
1593 2172923 : NewObjectGCKind(JSContext *cx, js::Class *clasp)
1594 : {
1595 2172923 : if (clasp == &ArrayClass || clasp == &SlowArrayClass)
1596 0 : return gc::FINALIZE_OBJECT8;
1597 2172923 : if (clasp == &FunctionClass)
1598 0 : return gc::FINALIZE_OBJECT2;
1599 2172923 : return gc::FINALIZE_OBJECT4;
1600 : }
1601 :
1602 : /*
1603 : * Fill slots with the initial slot array to use for a newborn object which
1604 : * may or may not need dynamic slots.
1605 : */
1606 : inline bool
1607 5689289 : PreallocateObjectDynamicSlots(JSContext *cx, Shape *shape, HeapSlot **slots)
1608 : {
1609 5689289 : if (size_t count = JSObject::dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan())) {
1610 32975 : *slots = (HeapSlot *) cx->malloc_(count * sizeof(HeapSlot));
1611 32975 : if (!*slots)
1612 0 : return false;
1613 32975 : Debug_SetSlotRangeToCrashOnTouch(*slots, count);
1614 32975 : return true;
1615 : }
1616 5656314 : *slots = NULL;
1617 5656314 : return true;
1618 : }
1619 :
1620 : inline bool
1621 70814 : DefineConstructorAndPrototype(JSContext *cx, GlobalObject *global,
1622 : JSProtoKey key, JSObject *ctor, JSObject *proto)
1623 : {
1624 70814 : JS_ASSERT(!global->nativeEmpty()); /* reserved slots already allocated */
1625 70814 : JS_ASSERT(ctor);
1626 70814 : JS_ASSERT(proto);
1627 :
1628 70814 : jsid id = ATOM_TO_JSID(cx->runtime->atomState.classAtoms[key]);
1629 70814 : JS_ASSERT(!global->nativeLookup(cx, id));
1630 :
1631 : /* Set these first in case AddTypePropertyId looks for this class. */
1632 70814 : global->setSlot(key, ObjectValue(*ctor));
1633 70814 : global->setSlot(key + JSProto_LIMIT, ObjectValue(*proto));
1634 70814 : global->setSlot(key + JSProto_LIMIT * 2, ObjectValue(*ctor));
1635 :
1636 70814 : types::AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
1637 70814 : if (!global->addDataProperty(cx, id, key + JSProto_LIMIT * 2, 0)) {
1638 0 : global->setSlot(key, UndefinedValue());
1639 0 : global->setSlot(key + JSProto_LIMIT, UndefinedValue());
1640 0 : global->setSlot(key + JSProto_LIMIT * 2, UndefinedValue());
1641 0 : return false;
1642 : }
1643 :
1644 70814 : return true;
1645 : }
1646 :
1647 : bool
1648 299098 : PropDesc::checkGetter(JSContext *cx)
1649 : {
1650 299098 : if (hasGet && !js_IsCallable(get) && !get.isUndefined()) {
1651 : JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_GET_SET_FIELD,
1652 18 : js_getter_str);
1653 18 : return false;
1654 : }
1655 299080 : return true;
1656 : }
1657 :
1658 : bool
1659 4313 : PropDesc::checkSetter(JSContext *cx)
1660 : {
1661 4313 : if (hasSet && !js_IsCallable(set) && !set.isUndefined()) {
1662 : JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_GET_SET_FIELD,
1663 0 : js_setter_str);
1664 0 : return false;
1665 : }
1666 4313 : return true;
1667 : }
1668 :
1669 : inline bool
1670 726168 : ObjectClassIs(JSObject &obj, ESClassValue classValue, JSContext *cx)
1671 : {
1672 726168 : if (JS_UNLIKELY(obj.isProxy()))
1673 594 : return Proxy::objectClassIs(&obj, classValue, cx);
1674 :
1675 725574 : switch (classValue) {
1676 1081 : case ESClass_Array: return obj.isArray();
1677 378 : case ESClass_Number: return obj.isNumber();
1678 369 : case ESClass_String: return obj.isString();
1679 342 : case ESClass_Boolean: return obj.isBoolean();
1680 723404 : case ESClass_RegExp: return obj.isRegExp();
1681 : }
1682 0 : JS_NOT_REACHED("bad classValue");
1683 : return false;
1684 : }
1685 :
1686 : inline bool
1687 918829 : IsObjectWithClass(const Value &v, ESClassValue classValue, JSContext *cx)
1688 : {
1689 918829 : if (!v.isObject())
1690 556722 : return false;
1691 362107 : return ObjectClassIs(v.toObject(), classValue, cx);
1692 : }
1693 :
1694 : static JS_ALWAYS_INLINE bool
1695 3207311 : ValueIsSpecial(JSObject *obj, Value *propval, SpecialId *sidp, JSContext *cx)
1696 : {
1697 3207311 : if (!propval->isObject())
1698 3207074 : return false;
1699 :
1700 : #if JS_HAS_XML_SUPPORT
1701 237 : if (obj->isXML()) {
1702 0 : *sidp = SpecialId(propval->toObject());
1703 0 : return true;
1704 : }
1705 :
1706 237 : JSObject &propobj = propval->toObject();
1707 : JSAtom *name;
1708 237 : if (propobj.isQName() && GetLocalNameFromFunctionQName(&propobj, &name, cx)) {
1709 0 : propval->setString(name);
1710 0 : return false;
1711 : }
1712 : #endif
1713 :
1714 237 : return false;
1715 : }
1716 :
1717 : JSObject *
1718 : DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey key, HandleAtom atom,
1719 : JSObject *protoProto, Class *clasp,
1720 : Native constructor, unsigned nargs,
1721 : JSPropertySpec *ps, JSFunctionSpec *fs,
1722 : JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
1723 : JSObject **ctorp = NULL,
1724 : gc::AllocKind ctorKind = JSFunction::FinalizeKind);
1725 :
1726 : } /* namespace js */
1727 :
1728 : extern JSObject *
1729 : js_InitClass(JSContext *cx, js::HandleObject obj, JSObject *parent_proto,
1730 : js::Class *clasp, JSNative constructor, unsigned nargs,
1731 : JSPropertySpec *ps, JSFunctionSpec *fs,
1732 : JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
1733 : JSObject **ctorp = NULL,
1734 : js::gc::AllocKind ctorKind = JSFunction::FinalizeKind);
1735 :
1736 : inline JSObject *
1737 20620590 : js_GetProtoIfDenseArray(JSObject *obj)
1738 : {
1739 20620590 : return obj->isDenseArray() ? obj->getProto() : obj;
1740 : }
1741 :
1742 : /*
1743 : * js_PurgeScopeChain does nothing if obj is not itself a prototype or parent
1744 : * scope, else it reshapes the scope and prototype chains it links. It calls
1745 : * js_PurgeScopeChainHelper, which asserts that obj is flagged as a delegate
1746 : * (i.e., obj has ever been on a prototype or parent chain).
1747 : */
1748 : extern bool
1749 : js_PurgeScopeChainHelper(JSContext *cx, JSObject *obj, jsid id);
1750 :
1751 : inline bool
1752 31574075 : js_PurgeScopeChain(JSContext *cx, JSObject *obj, jsid id)
1753 : {
1754 31574075 : if (obj->isDelegate())
1755 626973 : return js_PurgeScopeChainHelper(cx, obj, id);
1756 30947102 : return true;
1757 : }
1758 :
1759 : inline void
1760 25246 : js::DestroyIdArray(FreeOp *fop, JSIdArray *ida)
1761 : {
1762 25246 : fop->free_(ida);
1763 25246 : }
1764 :
1765 : #endif /* jsobjinlines_h___ */
|