static void GeneratePrototypeGuards(CacheIRWriter& writer, JSObject* obj, JSObject* holder, ObjOperandId objId) { // The guards here protect against the effects of JSObject::swap(). If the // prototype chain is directly altered, then TI will toss the jitcode, so we // don't have to worry about it, and any other change to the holder, or // adding a shadowing property will result in reshaping the holder, and thus // the failure of the shape guard. MOZ_ASSERT(obj != holder); if (obj->hasUncacheableProto()) { // If the shape does not imply the proto, emit an explicit proto guard. writer.guardProto(objId, obj->getProto()); } JSObject* pobj = IsCacheableDOMProxy(obj) ? obj->getTaggedProto().toObjectOrNull() : obj->getProto(); if (!pobj) return; while (pobj != holder) { if (pobj->hasUncacheableProto()) { ObjOperandId protoId = writer.loadObject(pobj); if (pobj->isSingleton()) { // Singletons can have their group's |proto| mutated directly. writer.guardProto(protoId, pobj->getProto()); } else { writer.guardGroup(protoId, pobj->group()); } } pobj = pobj->getProto(); } }
bool GetPropIRGenerator::tryAttachModuleNamespace(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId) { MOZ_ASSERT(!emitted_); if (!obj->is<ModuleNamespaceObject>()) return true; Rooted<ModuleNamespaceObject*> ns(cx_, &obj->as<ModuleNamespaceObject>()); RootedModuleEnvironmentObject env(cx_); RootedShape shape(cx_); if (!ns->bindings().lookup(NameToId(name_), env.address(), shape.address())) return true; // Don't emit a stub until the target binding has been initialized. if (env->getSlot(shape->slot()).isMagic(JS_UNINITIALIZED_LEXICAL)) return true; if (IsIonEnabled(cx_)) EnsureTrackPropertyTypes(cx_, env, shape->propid()); emitted_ = true; // Check for the specific namespace object. writer.guardSpecificObject(objId, ns); ObjOperandId envId = writer.loadObject(env); EmitLoadSlotResult(writer, envId, env, shape); return true; }
static void EmitCallGetterResult(CacheIRWriter& writer, JSObject* obj, JSObject* holder, Shape* shape, ObjOperandId objId) { Maybe<ObjOperandId> expandoId; TestMatchingReceiver(writer, obj, shape, objId, &expandoId); if (obj != holder) { GeneratePrototypeGuards(writer, obj, holder, objId); // Guard on the holder's shape. ObjOperandId holderId = writer.loadObject(holder); writer.guardShape(holderId, holder->as<NativeObject>().lastProperty()); } EmitCallGetterResultNoGuards(writer, obj, holder, shape, objId); }
static void EmitReadSlotResult(CacheIRWriter& writer, JSObject* obj, JSObject* holder, Shape* shape, ObjOperandId objId) { Maybe<ObjOperandId> expandoId; TestMatchingReceiver(writer, obj, shape, objId, &expandoId); ObjOperandId holderId; if (obj != holder) { GeneratePrototypeGuards(writer, obj, holder, objId); if (holder) { // Guard on the holder's shape. holderId = writer.loadObject(holder); writer.guardShape(holderId, holder->as<NativeObject>().lastProperty()); } else { // The property does not exist. Guard on everything in the prototype // chain. This is guaranteed to see only Native objects because of // CanAttachNativeGetProp(). JSObject* proto = obj->taggedProto().toObjectOrNull(); ObjOperandId lastObjId = objId; while (proto) { ObjOperandId protoId = writer.loadProto(lastObjId); writer.guardShape(protoId, proto->as<NativeObject>().lastProperty()); proto = proto->staticPrototype(); lastObjId = protoId; } } } else if (obj->is<UnboxedPlainObject>()) { holder = obj->as<UnboxedPlainObject>().maybeExpando(); holderId = *expandoId; } else { holderId = objId; } // Slot access. if (holder) { MOZ_ASSERT(holderId.valid()); EmitLoadSlotResult(writer, holderId, &holder->as<NativeObject>(), shape); } else { MOZ_ASSERT(!holderId.valid()); writer.loadUndefinedResult(); } }