SSATmp* IRBuilder::preOptimizeDecRefLoc(IRInstruction* inst) { auto const locId = inst->extra<DecRefLoc>()->locId; /* * Refine the type if we can. * * We can't really rely on the types held in the boxed values since aliasing * stores may change them, and we only guard during LdRef. So we have to * change any boxed type to BoxedCell. * * DataTypeGeneric is used because we don't want a DecRef to be the only * thing keeping a guard around. This code is designed to tolerate the * incoming type being relaxed. */ auto knownType = localType(locId, DataTypeGeneric); if (knownType.isBoxed()) { knownType = Type::BoxedCell; } /* * If we have the local value in flight, use a DecRef on it instead of doing * it in memory. */ if (auto tmp = localValue(locId, DataTypeGeneric)) { gen(DecRef, tmp); inst->convertToNop(); return nullptr; } if (!typeMightRelax()) { inst->setTypeParam(std::min(knownType, inst->typeParam())); } return nullptr; }
SSATmp* IRBuilder::preOptimizeStLoc(IRInstruction* inst) { // Guard relaxation might change the current local type, so don't try to // change to StLocNT until after relaxation happens. if (typeMightRelax()) return nullptr; auto locId = inst->extra<StLoc>()->locId; auto const curType = localType(locId, DataTypeGeneric); auto const newType = inst->src(1)->type(); assert(!inst->hasTypeParam()); /* * There's no need to store the type if it's going to be the same * KindOfFoo. We'll still have to store string types because we * aren't specific about storing KindOfStaticString * vs. KindOfString, and a Type::Null might mean KindOfUninit or * KindOfNull. */ auto const bothBoxed = curType.isBoxed() && newType.isBoxed(); auto const sameUnboxed = [&] { auto avoidable = { Type::Uninit, Type::InitNull, Type::Bool, Type::Int, Type::Dbl, // No strings. Type::Arr, Type::Obj, Type::Res }; for (auto t : avoidable) { if (curType <= t && newType <= t) return true; } return false; }; if (bothBoxed || sameUnboxed()) { inst->setOpcode(StLocNT); } return nullptr; }
inline bool unionTypeMightRelax(const IRInstruction* inst, IdxSeq<Idx, Rest...>) { assertx(Idx < inst->numSrcs()); return typeMightRelax(inst->src(Idx)) || unionTypeMightRelax(inst, IdxSeq<Rest...>{}); }