bool js::GetOwnProperty(JSContext *cx, Handle<ObjectImpl*> obj, PropertyId pid_, unsigned resolveFlags, PropDesc *desc) { NEW_OBJECT_REPRESENTATION_ONLY(); JS_CHECK_RECURSION(cx, return false); Rooted<PropertyId> pid(cx, pid_); if (static_cast<JSObject *>(obj.get())->isProxy()) { MOZ_NOT_REACHED("NYI: proxy [[GetOwnProperty]]"); return false; } /* |shape| is always set /after/ a GC. */ UnrootedShape shape = obj->nativeLookup(cx, pid); if (!shape) { DropUnrooted(shape); /* Not found: attempt to resolve it. */ Class *clasp = obj->getClass(); JSResolveOp resolve = clasp->resolve; if (resolve != JS_ResolveStub) { Rooted<jsid> id(cx, pid.get().asId()); Rooted<JSObject*> robj(cx, static_cast<JSObject*>(obj.get())); if (clasp->flags & JSCLASS_NEW_RESOLVE) { Rooted<JSObject*> obj2(cx, NULL); JSNewResolveOp op = reinterpret_cast<JSNewResolveOp>(resolve); if (!op(cx, robj, id, resolveFlags, &obj2)) return false; } else { if (!resolve(cx, robj, id)) return false; } } /* Now look it up again. */ shape = obj->nativeLookup(cx, pid); if (!shape) { desc->setUndefined(); return true; } } if (shape->isDataDescriptor()) { *desc = PropDesc(obj->nativeGetSlot(shape->slot()), shape->writability(), shape->enumerability(), shape->configurability()); return true; } if (shape->isAccessorDescriptor()) { *desc = PropDesc(shape->getterValue(), shape->setterValue(), shape->enumerability(), shape->configurability()); return true; } MOZ_NOT_REACHED("NYI: PropertyOp-based properties"); return false; }
static LookupStatus UpdateSetGlobalName(VMFrame &f, ic::SetGlobalNameIC *ic, JSObject *obj, UnrootedShape shape) { /* Give globals a chance to appear. */ if (!shape) return Lookup_Uncacheable; if (!shape->hasDefaultSetter() || !shape->writable() || !shape->hasSlot() || obj->watched()) { /* Disable the IC for weird shape attributes and watchpoints. */ PatchSetFallback(f, ic); return Lookup_Uncacheable; } /* Object is not branded, so we can use the inline path. */ Repatcher repatcher(f.chunk()); ic->patchInlineShapeGuard(repatcher, obj->lastProperty()); uint32_t index = obj->dynamicSlotIndex(shape->slot()); JSC::CodeLocationLabel label = ic->fastPathStart.labelAtOffset(ic->loadStoreOffset); repatcher.patchAddressOffsetForValueStore(label, index * sizeof(Value), ic->vr.isTypeKnown()); return Lookup_Cacheable; }
void js::ObjectImpl::checkShapeConsistency() { static int throttle = -1; if (throttle < 0) { if (const char *var = getenv("JS_CHECK_SHAPE_THROTTLE")) throttle = atoi(var); if (throttle < 0) throttle = 0; } if (throttle == 0) return; MOZ_ASSERT(isNative()); UnrootedShape shape = lastProperty(); UnrootedShape prev = NULL; if (inDictionaryMode()) { MOZ_ASSERT(shape->hasTable()); ShapeTable &table = shape->table(); for (uint32_t fslot = table.freelist; fslot != SHAPE_INVALID_SLOT; fslot = getSlot(fslot).toPrivateUint32()) { MOZ_ASSERT(fslot < slotSpan()); } for (int n = throttle; --n >= 0 && shape->parent; shape = shape->parent) { MOZ_ASSERT_IF(lastProperty() != shape, !shape->hasTable()); Shape **spp = table.search(shape->propid(), false); MOZ_ASSERT(SHAPE_FETCH(spp) == shape); } shape = lastProperty(); for (int n = throttle; --n >= 0 && shape; shape = shape->parent) { MOZ_ASSERT_IF(shape->slot() != SHAPE_INVALID_SLOT, shape->slot() < slotSpan()); if (!prev) { MOZ_ASSERT(lastProperty() == shape); MOZ_ASSERT(shape->listp == &shape_); } else { MOZ_ASSERT(shape->listp == &prev->parent); } prev = shape; } } else { for (int n = throttle; --n >= 0 && shape->parent; shape = shape->parent) { if (shape->hasTable()) { ShapeTable &table = shape->table(); MOZ_ASSERT(shape->parent); for (Shape::Range r(shape); !r.empty(); r.popFront()) { Shape **spp = table.search(r.front().propid(), false); MOZ_ASSERT(SHAPE_FETCH(spp) == &r.front()); } } if (prev) { MOZ_ASSERT(prev->maybeSlot() >= shape->maybeSlot()); shape->kids.checkConsistency(prev); } prev = shape; } } }