SSATmp* ldClsPropAddr(IRGS& env, SSATmp* ssaCls, SSATmp* ssaName, bool raise) { /* * We can use ldClsPropAddrKnown if either we know which property it is and * that it is visible && accessible, or we know it is a property on this * class itself. */ bool const sPropKnown = [&] { if (!ssaName->hasConstVal()) return false; auto const propName = ssaName->strVal(); if (!ssaCls->hasConstVal()) return false; auto const cls = ssaCls->clsVal(); if (!classIsPersistentOrCtxParent(env, cls)) return false; auto const lookup = cls->findSProp(curClass(env), propName); return lookup.prop != kInvalidSlot && lookup.accessible; }(); if (sPropKnown) { return ldClsPropAddrKnown(env, ssaCls->clsVal(), ssaName->strVal()); } return gen( env, raise ? LdClsPropAddrOrRaise : LdClsPropAddrOrNull, ssaCls, ssaName, cns(env, curClass(env)) ); }
void inlSingletonSProp(IRGS& env, const Func* func, const Op* clsOp, const Op* propOp) { assertx(*clsOp == Op::String); assertx(*propOp == Op::String); TransFlags trflags; trflags.noinlineSingleton = true; auto exitBlock = makeExit(env, trflags); // Pull the class and property names. auto const unit = func->unit(); auto const clsName = unit->lookupLitstrId(getImmPtr(clsOp, 0)->u_SA); auto const propName = unit->lookupLitstrId(getImmPtr(propOp, 0)->u_SA); // Make sure we have a valid class. auto const cls = Unit::lookupClass(clsName); if (UNLIKELY(!classHasPersistentRDS(cls))) { PUNT(SingletonSProp-Persistent); } // Make sure the sprop is accessible from the singleton method's context. auto const lookup = cls->findSProp(func->cls(), propName); if (UNLIKELY(lookup.prop == kInvalidSlot || !lookup.accessible)) { PUNT(SingletonSProp-Accessibility); } // Look up the static property. auto const sprop = ldClsPropAddrKnown(env, cls, propName); auto const unboxed = gen(env, UnboxPtr, sprop); auto const value = gen(env, LdMem, unboxed->type().deref(), unboxed); // Side exit if the static property is null. auto isnull = gen(env, IsType, TNull, value); gen(env, JmpNZero, exitBlock, isnull); // Return the singleton. pushIncRef(env, value); }