void Shape::removeChild(Shape *child) { JS_ASSERT(!child->inDictionary()); JS_ASSERT(child->parent == this); KidsPointer *kidp = &kids; if (kidp->isShape()) { JS_ASSERT(kidp->toShape() == child); kidp->setNull(); child->parent = nullptr; return; } KidsHash *hash = kidp->toHash(); JS_ASSERT(hash->count() >= 2); /* otherwise kidp->isShape() should be true */ hash->remove(StackShape(child)); child->parent = nullptr; if (hash->count() == 1) { /* Convert from HASH form back to SHAPE form. */ KidsHash::Range r = hash->all(); Shape *otherChild = r.front(); JS_ASSERT((r.popFront(), r.empty())); /* No more elements! */ kidp->setShape(otherChild); js_delete(hash); } }
JS_ALWAYS_INLINE void js::PropertyTree::orphanChildren(Shape *shape) { KidsPointer *kidp = &shape->kids; JS_ASSERT(!kidp->isNull()); if (kidp->isShape()) { Shape *kid = kidp->toShape(); if (!JSID_IS_VOID(kid->id)) { JS_ASSERT(kid->parent == shape); kid->parent = NULL; } } else { KidsHash *hash = kidp->toHash(); for (KidsHash::Range range = hash->all(); !range.empty(); range.popFront()) { Shape *kid = range.front(); if (!JSID_IS_VOID(kid->id)) { JS_ASSERT(kid->parent == shape); kid->parent = NULL; } } hash->~KidsHash(); js_free(hash); } kidp->setNull(); }
void Shape::dumpSubtree(JSContext *cx, int level, FILE *fp) const { if (!parent) { JS_ASSERT(level == 0); JS_ASSERT(JSID_IS_EMPTY(propid_)); fprintf(fp, "class %s emptyShape\n", getObjectClass()->name); } else { fprintf(fp, "%*sid ", level, ""); dump(cx, fp); } if (!kids.isNull()) { ++level; if (kids.isShape()) { Shape *kid = kids.toShape(); JS_ASSERT(kid->parent == this); kid->dumpSubtree(cx, level, fp); } else { const KidsHash &hash = *kids.toHash(); for (KidsHash::Range range = hash.all(); !range.empty(); range.popFront()) { Shape *kid = range.front(); JS_ASSERT(kid->parent == this); kid->dumpSubtree(cx, level, fp); } } } }
void js::PropertyTree::meter(JSBasicStats *bs, Shape *node) { uintN nkids = 0; const KidsPointer &kidp = node->kids; if (kidp.isShape()) { meter(bs, kidp.toShape()); nkids = 1; } else if (kidp.isHash()) { const KidsHash &hash = *kidp.toHash(); for (KidsHash::Range range = hash.all(); !range.empty(); range.popFront()) { Shape *kid = range.front(); meter(bs, kid); nkids++; } } MeterKidCount(bs, nkids); }