Beispiel #1
0
/*
 * Note: this is currently separate from typeFromRAT for now, just because we
 * don't want to enable every single type for assertions yet.
 *
 * (Some of them currently regress performance, presumably because the IR
 * doesn't always handle the additional type information very well.  It is
 * possibly a compile-time slowdown only, but we haven't investigated yet.)
 */
folly::Optional<Type> ratToAssertType(IRGS& env, RepoAuthType rat) {
  using T = RepoAuthType::Tag;

  switch (rat.tag()) {
    case T::Uninit:
    case T::InitNull:
    case T::Null:
    case T::Bool:
    case T::Int:
    case T::Dbl:
    case T::Res:
    case T::SStr:
    case T::Str:
    case T::Obj:
    case T::SArr:
    case T::Arr:
    case T::Cell:
    case T::Ref:
    case T::InitUnc:
    case T::Unc:
      return typeFromRAT(rat);

    case T::OptExactObj:
    case T::OptSubObj:
    case T::ExactObj:
    case T::SubObj: {
      auto ty = typeFromRAT(rat);
      auto const cls = Unit::lookupClassOrUniqueClass(rat.clsName());

      if (!classIsUniqueOrCtxParent(env, cls)) {
        ty |= TObj; // Kill specialization.
      }
      return ty;
    }

    // Type assertions can't currently handle Init-ness.
    case T::InitCell:
      return TCell;
    case T::InitGen:
      return folly::none;

    case T::Gen:
      return folly::none;

    case T::OptInt:
    case T::OptObj:
    case T::OptDbl:
    case T::OptBool:
    case T::OptSStr:
    case T::OptStr:
    case T::OptRes:
      return folly::none;

    case T::OptSArr:
    case T::OptArr:
      // TODO(#4205897): optional array types.
      return folly::none;
  }
  not_reached();
}
Beispiel #2
0
// Simple stats about opcodes (that don't require full type
// information---those cases are only enabled when extendedStats is
// on).
void collect_simple(Stats& stats, const Bytecode& bc) {
  ++stats.op_counts[static_cast<uint64_t>(bc.op)];

  RepoAuthType rat;
  switch (bc.op) {
  case Op::AssertRATL:
    rat = bc.AssertRATL.rat;
    break;
  case Op::AssertRATStk:
    rat = bc.AssertRATStk.rat;
    break;
  default:
    return;
  }

  using U = std::underlying_type<RepoAuthType::Tag>::type;
  auto const tagInt = static_cast<U>(rat.tag());
  assert(tagInt < stats.ratL_tags.size());
  if (bc.op == Op::AssertRATL) {
    ++stats.ratL_tags[tagInt];
  } else {
    ++stats.ratStk_tags[tagInt];
  }

  if (rat.mayHaveArrData()) {
    if (rat.array()) {
      if (bc.op == Op::AssertRATL) {
        ++stats.ratL_specialized_array;
      } else {
        ++stats.ratStk_specialized_array;
      }
    }
  }
}
Beispiel #3
0
Type convertToType(RepoAuthType ty) {
  using T = RepoAuthType::Tag;
  switch (ty.tag()) {
  case T::OptBool:        return Type::Bool      | Type::InitNull;
  case T::OptInt:         return Type::Int       | Type::InitNull;
  case T::OptSStr:        return Type::StaticStr | Type::InitNull;
  case T::OptStr:         return Type::Str       | Type::InitNull;
  case T::OptDbl:         return Type::Dbl       | Type::InitNull;
  case T::OptRes:         return Type::Res       | Type::InitNull;
  case T::OptObj:         return Type::Obj       | Type::InitNull;

  case T::Uninit:         return Type::Uninit;
  case T::InitNull:       return Type::InitNull;
  case T::Null:           return Type::Null;
  case T::Bool:           return Type::Bool;
  case T::Int:            return Type::Int;
  case T::Dbl:            return Type::Dbl;
  case T::Res:            return Type::Res;
  case T::SStr:           return Type::StaticStr;
  case T::Str:            return Type::Str;
  case T::Obj:            return Type::Obj;

  case T::Cell:           return Type::Cell;
  case T::Ref:            return Type::BoxedCell;
  case T::InitUnc:        return Type::UncountedInit;
  case T::Unc:            return Type::Uncounted;
  case T::InitCell:       return Type::InitCell;
  case T::InitGen:        return Type::Init;
  case T::Gen:            return Type::Gen;

  // TODO(#4205897): option specialized array types
  case T::OptArr:         return Type::Arr       | Type::InitNull;
  case T::OptSArr:        return Type::StaticArr | Type::InitNull;

  case T::SArr:
    if (auto const ar = ty.array()) return Type::StaticArr.specialize(ar);
    return Type::StaticArr;
  case T::Arr:
    if (auto const ar = ty.array()) return Type::Arr.specialize(ar);
    return Type::Arr;

  case T::SubObj:
  case T::ExactObj:
    if (auto const cls = Unit::lookupUniqueClass(ty.clsName())) {
      return Type::Obj.specialize(cls);
    }
    return Type::Obj;
  case T::OptSubObj:
  case T::OptExactObj:
    if (auto const cls = Unit::lookupUniqueClass(ty.clsName())) {
      return Type::Obj.specialize(cls) | Type::InitNull;
    }
    return Type::Obj | Type::InitNull;
  }
  not_reached();
}
Beispiel #4
0
bool RepoAuthType::operator==(RepoAuthType o) const {
    using T = Tag;
    if (tag() != o.tag()) return false;
    switch (tag()) {
    case T::OptBool:
    case T::OptInt:
    case T::OptSStr:
    case T::OptStr:
    case T::OptDbl:
    case T::OptRes:
    case T::OptObj:
    case T::Null:
    case T::Cell:
    case T::Ref:
    case T::InitUnc:
    case T::Unc:
    case T::InitCell:
    case T::InitGen:
    case T::Gen:
    case T::Uninit:
    case T::InitNull:
    case T::Bool:
    case T::Int:
    case T::Dbl:
    case T::Res:
    case T::SStr:
    case T::Str:
    case T::Obj:
        return true;

    case T::OptSArr:
    case T::OptArr:
        // Can't currently have array() info.
        return true;

    case T::SArr:
    case T::Arr:
        if (array() == nullptr && o.array() == nullptr) {
            return true;
        }
        if ((array() == nullptr) != (o.array() == nullptr)) {
            return false;
        }
        return array()->id() == o.array()->id();

    case T::SubObj:
    case T::ExactObj:
    case T::OptSubObj:
    case T::OptExactObj:
        return clsName() == o.clsName();
    }
    not_reached();
}
Beispiel #5
0
void merge_repo_auth_type(UnitEmitter& ue, RepoAuthType rat) {
  using T = RepoAuthType::Tag;

  switch (rat.tag()) {
  case T::OptBool:
  case T::OptInt:
  case T::OptSStr:
  case T::OptStr:
  case T::OptDbl:
  case T::OptRes:
  case T::OptObj:
  case T::Null:
  case T::Cell:
  case T::Ref:
  case T::InitUnc:
  case T::Unc:
  case T::InitCell:
  case T::InitGen:
  case T::Gen:
  case T::Uninit:
  case T::InitNull:
  case T::Bool:
  case T::Int:
  case T::Dbl:
  case T::Res:
  case T::SStr:
  case T::Str:
  case T::Obj:
    return;

  case T::OptSArr:
  case T::OptArr:
  case T::SArr:
  case T::Arr:
    // We don't need to merge the litstrs in the array, because rats
    // in arrays in the array type table must be using global litstr
    // ids.  (As the array type table itself is not associated with
    // any unit.)
    return;

  case T::OptSubObj:
  case T::OptExactObj:
  case T::SubObj:
  case T::ExactObj:
    ue.mergeLitstr(rat.clsName());
    return;
  }
}
Beispiel #6
0
folly::Optional<DataType> convertToDataType(RepoAuthType ty) {
  using T = RepoAuthType::Tag;
  switch (ty.tag()) {
  case T::OptBool:
  case T::OptInt:
  case T::OptSArr:
  case T::OptArr:
  case T::OptSVec:
  case T::OptVec:
  case T::OptSDict:
  case T::OptDict:
  case T::OptSKeyset:
  case T::OptKeyset:
  case T::OptSStr:
  case T::OptStr:
  case T::OptDbl:
  case T::OptRes:
  case T::OptSubObj:
  case T::OptExactObj:
  case T::OptObj:
  case T::Null:
    return folly::none;

  case T::Cell:
  case T::Ref:
  case T::InitUnc:
  case T::Unc:
  case T::InitCell:
  case T::InitGen:
  case T::Gen:
    return folly::none;

  case T::Uninit:       return KindOfUninit;
  case T::InitNull:     return KindOfNull;
  case T::Bool:         return KindOfBoolean;
  case T::Int:          return KindOfInt64;
  case T::Dbl:          return KindOfDouble;
  case T::Res:          return KindOfResource;

  case T::SStr:
  case T::Str:          return KindOfString;

  case T::SArr:
  case T::Arr:          return KindOfArray;

  case T::SVec:
  case T::Vec:          return KindOfVec;

  case T::SDict:
  case T::Dict:         return KindOfDict;

  case T::SKeyset:
  case T::Keyset:       return KindOfKeyset;

  case T::Obj:
  case T::SubObj:
  case T::ExactObj:     return KindOfObject;
  }
  not_reached();
}
void encodeRAT(UnitEmitter& ue, RepoAuthType rat) {
  using T = RepoAuthType::Tag;
  switch (rat.tag()) {
  case T::Uninit:
  case T::InitNull:
  case T::Null:
  case T::Int:
  case T::OptInt:
  case T::Dbl:
  case T::OptDbl:
  case T::Res:
  case T::OptRes:
  case T::Bool:
  case T::OptBool:
  case T::SStr:
  case T::OptSStr:
  case T::Str:
  case T::OptStr:
  case T::SVec:
  case T::OptSVec:
  case T::Vec:
  case T::OptVec:
  case T::SDict:
  case T::OptSDict:
  case T::Dict:
  case T::OptDict:
  case T::SKeyset:
  case T::OptSKeyset:
  case T::Keyset:
  case T::OptKeyset:
  case T::Obj:
  case T::OptObj:
  case T::UncArrKey:
  case T::ArrKey:
  case T::OptUncArrKey:
  case T::OptArrKey:
  case T::InitUnc:
  case T::Unc:
  case T::InitCell:
  case T::Cell:
  case T::Ref:
  case T::InitGen:
  case T::Gen:
    ue.emitByte(static_cast<uint8_t>(rat.tag()));
    break;

  case T::SArr:
  case T::OptSArr:
  case T::Arr:
  case T::OptArr:
  case T::SVArr:
  case T::OptSVArr:
  case T::VArr:
  case T::OptVArr:
  case T::SDArr:
  case T::OptSDArr:
  case T::DArr:
  case T::OptDArr:
    {
      auto tagByte = static_cast<uint8_t>(rat.tag());
      if (rat.hasArrData()) tagByte |= kRATArrayDataBit;
      ue.emitByte(tagByte);
      if (rat.hasArrData()) {
        ue.emitInt32(rat.arrayId());
      }
      break;
    }

  case T::ExactObj:
  case T::SubObj:
  case T::OptExactObj:
  case T::OptSubObj:
    ue.emitByte(static_cast<uint8_t>(rat.tag()));
    ue.emitInt32(ue.mergeLitstr(rat.clsName()));
    break;
  }
}
Beispiel #8
0
Type typeFromRAT(RepoAuthType ty) {
  using T = RepoAuthType::Tag;
  switch (ty.tag()) {
    case T::OptBool:        return TBool      | TInitNull;
    case T::OptInt:         return TInt       | TInitNull;
    case T::OptSStr:        return TStaticStr | TInitNull;
    case T::OptStr:         return TStr       | TInitNull;
    case T::OptDbl:         return TDbl       | TInitNull;
    case T::OptRes:         return TRes       | TInitNull;
    case T::OptObj:         return TObj       | TInitNull;

    case T::Uninit:         return TUninit;
    case T::InitNull:       return TInitNull;
    case T::Null:           return TNull;
    case T::Bool:           return TBool;
    case T::Int:            return TInt;
    case T::Dbl:            return TDbl;
    case T::Res:            return TRes;
    case T::SStr:           return TStaticStr;
    case T::Str:            return TStr;
    case T::Obj:            return TObj;

    case T::Cell:           return TCell;
    case T::Ref:            return TBoxedInitCell;
    case T::InitUnc:        return TUncountedInit;
    case T::Unc:            return TUncounted;
    case T::InitCell:       return TInitCell;
    case T::InitGen:        return TInitGen;
    case T::Gen:            return TGen;

    // TODO(#4205897): option specialized array types
    case T::OptArr:         return TArr       | TInitNull;
    case T::OptSArr:        return TStaticArr | TInitNull;

    case T::SArr:
      if (auto const ar = ty.array()) return Type::StaticArray(ar);
      return TStaticArr;
    case T::Arr:
      if (auto const ar = ty.array()) return Type::Array(ar);
      return TArr;

    case T::SubObj:
    case T::ExactObj:
    case T::OptSubObj:
    case T::OptExactObj: {
      auto base = TObj;

      if (auto const cls = Unit::lookupClassOrUniqueClass(ty.clsName())) {
        if (ty.tag() == T::ExactObj || ty.tag() == T::OptExactObj) {
          base = Type::ExactObj(cls);
        } else {
          base = Type::SubObj(cls);
        }
      }
      if (ty.tag() == T::OptSubObj || ty.tag() == T::OptExactObj) {
        base |= TInitNull;
      }
      return base;
    }
  }
  not_reached();
}
Beispiel #9
0
std::string show(RepoAuthType rat) {
    auto const tag = rat.tag();
    using T = RepoAuthType::Tag;
    switch (tag) {
    case T::OptBool:
        return "?Bool";
    case T::OptInt:
        return "?Int";
    case T::OptSStr:
        return "?SStr";
    case T::OptStr:
        return "?Str";
    case T::OptDbl:
        return "?Dbl";
    case T::OptRes:
        return "?Res";
    case T::OptObj:
        return "?Obj";
    case T::Null:
        return "Null";
    case T::Cell:
        return "Cell";
    case T::Ref:
        return "Ref";
    case T::InitUnc:
        return "InitUnc";
    case T::Unc:
        return "Unc";
    case T::InitCell:
        return "InitCell";
    case T::InitGen:
        return "InitGen";
    case T::Gen:
        return "Gen";
    case T::Uninit:
        return "Uninit";
    case T::InitNull:
        return "InitNull";
    case T::Bool:
        return "Bool";
    case T::Int:
        return "Int";
    case T::Dbl:
        return "Dbl";
    case T::Res:
        return "Res";
    case T::SStr:
        return "SStr";
    case T::Str:
        return "Str";
    case T::Obj:
        return "Obj";

    case T::OptSArr:
    case T::OptArr:
    case T::SArr:
    case T::Arr:
    {
        auto ret = std::string{};
        if (tag == T::OptArr || tag == T::OptSArr) {
            ret += '?';
        }
        if (tag == T::SArr || tag == T::OptSArr) {
            ret += 'S';
        }
        ret += "Arr";
        if (auto const ar = rat.array()) {
            folly::format(&ret, "{}", show(*ar));
        }
        return ret;
    }
    break;

    case T::OptSubObj:
    case T::OptExactObj:
    case T::SubObj:
    case T::ExactObj:
    {
        auto ret = std::string{};
        if (tag == T::OptSubObj || tag == T::OptExactObj) {
            ret += '?';
        }
        ret += "Obj";
        if (tag == T::OptSubObj || tag == T::SubObj) {
            ret += "<";
        }
        ret += '=';
        ret += rat.clsName()->data();
        return ret;
    }
    }
    not_reached();
}
Beispiel #10
0
bool tvMatchesRepoAuthType(TypedValue tv, RepoAuthType ty) {
    assert(tvIsPlausible(tv));

    bool const initNull = tv.m_type == KindOfNull;

    using T = RepoAuthType::Tag;
    switch (ty.tag()) {
    case T::Uninit:
        return tv.m_type == KindOfUninit;
    case T::InitNull:
        return initNull;

    case T::OptBool:
        if (initNull) return true;
    // fallthrough
    case T::Bool:
        return tv.m_type == KindOfBoolean;
    case T::OptInt:
        if (initNull) return true;
    // fallthrough
    case T::Int:
        return tv.m_type == KindOfInt64;
    case T::OptDbl:
        if (initNull) return true;
    // fallthrough
    case T::Dbl:
        return tv.m_type == KindOfDouble;
    case T::OptRes:
        if (initNull) return true;
    // fallthrough
    case T::Res:
        return tv.m_type == KindOfResource;
    case T::OptObj:
        if (initNull) return true;
    // fallthrough
    case T::Obj:
        return tv.m_type == KindOfObject;

    case T::OptSStr:
        if (initNull) return true;
    // fallthrough
    case T::SStr:
        return tv.m_type == KindOfStaticString ||
               (tv.m_type == KindOfString && tv.m_data.pstr->isStatic());

    case T::OptStr:
        if (initNull) return true;
    // fallthrough
    case T::Str:
        return IS_STRING_TYPE(tv.m_type);

    case T::OptSArr:
        if (initNull) return true;
    // fallthrough
    case T::SArr:
        if (tv.m_type != KindOfArray || !tv.m_data.parr->isStatic()) {
            return false;
        }
        if (auto const arr = ty.array()) {
            if (!tvMatchesArrayType(tv, arr)) return false;
        }
        return true;

    case T::OptArr:
        if (initNull) return true;
    // fallthrough
    case T::Arr:
        if (tv.m_type != KindOfArray) return false;
        if (auto const arr = ty.array()) {
            if (!tvMatchesArrayType(tv, arr)) return false;
        }
        return true;

    case T::Null:
        return initNull || tv.m_type == KindOfUninit;

    case T::OptSubObj:
        if (initNull) return true;
    // fallthrough
    case T::SubObj:
    {
        auto const cls = Unit::lookupClass(ty.clsName());
        if (!cls) return false;
        return tv.m_type == KindOfObject &&
               tv.m_data.pobj->getVMClass()->classof(cls);
    }

    case T::OptExactObj:
        if (initNull) return true;
    // fallthrough
    case T::ExactObj:
    {
        auto const cls = Unit::lookupClass(ty.clsName());
        if (!cls) return false;
        return tv.m_type == KindOfObject && tv.m_data.pobj->getVMClass() == cls;
    }

    case T::InitUnc:
        if (tv.m_type == KindOfUninit) return false;
    // fallthrough
    case T::Unc:
        return !IS_REFCOUNTED_TYPE(tv.m_type) ||
               (tv.m_type == KindOfString && tv.m_data.pstr->isStatic()) ||
               (tv.m_type == KindOfArray && tv.m_data.parr->isStatic());

    case T::InitCell:
        if (tv.m_type == KindOfUninit) return false;
    // fallthrough
    case T::Cell:
        return tv.m_type != KindOfRef;

    case T::Ref:
        return tv.m_type == KindOfRef;

    case T::InitGen:
        if (tv.m_type == KindOfUninit) return false;
    // fallthrough
    case T::Gen:
        return true;
    }
    not_reached();
}
Beispiel #11
0
std::string show(RepoAuthType rat) {
  auto const tag = rat.tag();
  using T = RepoAuthType::Tag;
  switch (tag) {
  case T::OptBool:  return "?Bool";
  case T::OptInt:   return "?Int";
  case T::OptSStr:  return "?SStr";
  case T::OptStr:   return "?Str";
  case T::OptDbl:   return "?Dbl";
  case T::OptRes:   return "?Res";
  case T::OptObj:   return "?Obj";
  case T::OptUncArrKey: return "?UncArrKey";
  case T::OptArrKey: return "?ArrKey";
  case T::Null:     return "Null";
  case T::Cell:     return "Cell";
  case T::Ref:      return "Ref";
  case T::InitUnc:  return "InitUnc";
  case T::Unc:      return "Unc";
  case T::UncArrKey:return "UncArrKey";
  case T::ArrKey:   return "ArrKey";
  case T::InitCell: return "InitCell";
  case T::InitGen:  return "InitGen";
  case T::Gen:      return "Gen";
  case T::Uninit:   return "Uninit";
  case T::InitNull: return "InitNull";
  case T::Bool:     return "Bool";
  case T::Int:      return "Int";
  case T::Dbl:      return "Dbl";
  case T::Res:      return "Res";
  case T::SStr:     return "SStr";
  case T::Str:      return "Str";
  case T::Obj:      return "Obj";

  case T::OptSArr:
  case T::OptArr:
  case T::SArr:
  case T::Arr:
  case T::OptSVArr:
  case T::OptVArr:
  case T::SVArr:
  case T::VArr:
  case T::OptSDArr:
  case T::OptDArr:
  case T::SDArr:
  case T::DArr:
    {
      auto ret = std::string{};
      if (tag == T::OptArr || tag == T::OptSArr ||
          tag == T::OptVArr || tag == T::OptSVArr ||
          tag == T::OptDArr || tag == T::OptSDArr) {
        ret += '?';
      }
      if (tag == T::SArr || tag == T::OptSArr ||
          tag == T::SVArr || tag == T::OptSVArr ||
          tag == T::SDArr || tag == T::OptSDArr) {
        ret += 'S';
      }
      if (tag == T::OptArr || tag == T::Arr ||
          tag == T::OptSArr || tag == T::SArr) {
        ret += "Arr";
      } else if (tag == T::OptVArr || tag == T::VArr ||
                 tag == T::OptSVArr || tag == T::SVArr) {
        ret += "VArr";
      } else {
        ret += "DArr";
      }
      if (rat.hasArrData()) folly::format(&ret, "{}", show(*rat.array()));
      return ret;
    }
    break;

  case T::SVec:        return "SVec";
  case T::Vec:         return "Vec";
  case T::OptSVec:     return "?SVec";
  case T::OptVec:      return "?Vec";

  case T::SDict:       return "SDict";
  case T::Dict:        return "Dict";
  case T::OptSDict:    return "?SDict";
  case T::OptDict:     return "?Dict";

  case T::SKeyset:     return "SKeyset";
  case T::Keyset:      return "Keyset";
  case T::OptSKeyset:  return "?SKeyset";
  case T::OptKeyset:   return "?Keyset";

  case T::OptSubObj:
  case T::OptExactObj:
  case T::SubObj:
  case T::ExactObj:
    {
      auto ret = std::string{};
      if (tag == T::OptSubObj || tag == T::OptExactObj) {
        ret += '?';
      }
      ret += "Obj";
      if (tag == T::OptSubObj || tag == T::SubObj) {
        ret += "<";
      }
      ret += '=';
      ret += rat.clsName()->data();
      return ret;
    }
  }
  not_reached();
}
Beispiel #12
0
bool tvMatchesRepoAuthType(TypedValue tv, RepoAuthType ty) {
  assert(tvIsPlausible(tv));

  bool const initNull = tv.m_type == KindOfNull;

  using T = RepoAuthType::Tag;
  switch (ty.tag()) {
  case T::Uninit:       return tv.m_type == KindOfUninit;
  case T::InitNull:     return initNull;

  case T::OptBool:      if (initNull) return true;
                        // fallthrough
  case T::Bool:         return tv.m_type == KindOfBoolean;
  case T::OptInt:       if (initNull) return true;
                        // fallthrough
  case T::Int:          return tv.m_type == KindOfInt64;
  case T::OptDbl:       if (initNull) return true;
                        // fallthrough
  case T::Dbl:          return tv.m_type == KindOfDouble;
  case T::OptRes:       if (initNull) return true;
                        // fallthrough
  case T::Res:          return tv.m_type == KindOfResource;
  case T::OptObj:       if (initNull) return true;
                        // fallthrough
  case T::Obj:          return tv.m_type == KindOfObject;

  case T::OptSStr:
    if (initNull) return true;
    // fallthrough
  case T::SStr:
    return isStringType(tv.m_type) && tv.m_data.pstr->isStatic();

  case T::OptStr:
    if (initNull) return true;
    // fallthrough
  case T::Str:
    return isStringType(tv.m_type);

  case T::OptSArr:
    if (initNull) return true;
    // fallthrough
  case T::SArr:
    if (!isArrayType(tv.m_type) || !tv.m_data.parr->isStatic()) {
      return false;
    }
    if (auto const arr = ty.array()) {
      if (!tvMatchesArrayType(tv, arr)) return false;
    }
    return true;

  case T::OptArr:
    if (initNull) return true;
    // fallthrough
  case T::Arr:
    if (!isArrayType(tv.m_type)) return false;
    if (auto const arr = ty.array()) {
      if (!tvMatchesArrayType(tv, arr)) return false;
    }
    return true;

  case T::OptSVArr:
    if (initNull) return true;
    // fallthrough
  case T::SVArr:
    if (!isArrayType(tv.m_type) ||
        !tv.m_data.parr->isStatic() ||
        !tv.m_data.parr->isVArray()) {
      return false;
    }
    if (auto const arr = ty.array()) {
      if (!tvMatchesArrayType(tv, arr)) return false;
    }
    return true;

  case T::OptVArr:
    if (initNull) return true;
    // fallthrough
  case T::VArr:
    if (!isArrayType(tv.m_type) || !tv.m_data.parr->isVArray()) return false;
    if (auto const arr = ty.array()) {
      if (!tvMatchesArrayType(tv, arr)) return false;
    }
    return true;

  case T::OptSDArr:
    if (initNull) return true;
    // fallthrough
  case T::SDArr:
    if (!isArrayType(tv.m_type) ||
        !tv.m_data.parr->isStatic() ||
        !tv.m_data.parr->isDArray()) {
      return false;
    }
    if (auto const arr = ty.array()) {
      if (!tvMatchesArrayType(tv, arr)) return false;
    }
    return true;

  case T::OptDArr:
    if (initNull) return true;
    // fallthrough
  case T::DArr:
    if (!isArrayType(tv.m_type) || !tv.m_data.parr->isDArray()) return false;
    if (auto const arr = ty.array()) {
      if (!tvMatchesArrayType(tv, arr)) return false;
    }
    return true;

  case T::OptSVec:
    if (initNull) return true;
    // fallthrough
  case T::SVec:
    return isVecType(tv.m_type) && tv.m_data.parr->isStatic();

  case T::OptVec:
    if (initNull) return true;
    // fallthrough
  case T::Vec:
    return isVecType(tv.m_type);

  case T::OptSDict:
    if (initNull) return true;
    // fallthrough
  case T::SDict:
    return isDictType(tv.m_type) && tv.m_data.parr->isStatic();

  case T::OptDict:
    if (initNull) return true;
    // fallthrough
  case T::Dict:
    return isDictType(tv.m_type);

  case T::OptSKeyset:
    if (initNull) return true;
    // fallthrough
  case T::SKeyset:
    return isKeysetType(tv.m_type) && tv.m_data.parr->isStatic();

  case T::OptKeyset:
    if (initNull) return true;
    // fallthrough
  case T::Keyset:
    return isKeysetType(tv.m_type);

  case T::Null:
    return initNull || tv.m_type == KindOfUninit;

  case T::OptSubObj:
    if (initNull) return true;
    // fallthrough
  case T::SubObj:
    {
      auto const cls = Unit::lookupClass(ty.clsName());
      if (!cls) return false;
      return tv.m_type == KindOfObject &&
             tv.m_data.pobj->getVMClass()->classof(cls);
    }

  case T::OptExactObj:
    if (initNull) return true;
    // fallthrough
  case T::ExactObj:
    {
      auto const cls = Unit::lookupClass(ty.clsName());
      if (!cls) return false;
      return tv.m_type == KindOfObject && tv.m_data.pobj->getVMClass() == cls;
    }

  case T::InitUnc:
    if (tv.m_type == KindOfUninit) return false;
    // fallthrough
  case T::Unc:
    return !isRefcountedType(tv.m_type) ||
           (tv.m_type == KindOfString && tv.m_data.pstr->isStatic()) ||
           (isArrayLikeType(tv.m_type) && tv.m_data.parr->isStatic());

  case T::OptArrKey:
    if (initNull) return true;
    // fallthrough
  case T::ArrKey:
    return isStringType(tv.m_type) || tv.m_type == KindOfInt64;

  case T::OptUncArrKey:
    if (initNull) return true;
    // fallthrough
  case T::UncArrKey:
    return (isStringType(tv.m_type) && !tv.m_data.pstr->isRefCounted()) ||
      tv.m_type == KindOfInt64;

  case T::InitCell:
    if (tv.m_type == KindOfUninit) return false;
    // fallthrough
  case T::Cell:
    return tv.m_type != KindOfRef;

  case T::Ref:
    return tv.m_type == KindOfRef;

  case T::InitGen:
    if (tv.m_type == KindOfUninit) return false;
    // fallthrough
  case T::Gen:
    return true;
  }
  not_reached();
}
Beispiel #13
0
bool RepoAuthType::operator==(RepoAuthType o) const {
  using T = Tag;
  if (tag() != o.tag()) return false;
  switch (tag()) {
  case T::OptBool:
  case T::OptInt:
  case T::OptSStr:
  case T::OptStr:
  case T::OptDbl:
  case T::OptRes:
  case T::OptObj:
  case T::OptArrKey:
  case T::OptUncArrKey:
  case T::Null:
  case T::Cell:
  case T::Ref:
  case T::InitUnc:
  case T::Unc:
  case T::ArrKey:
  case T::UncArrKey:
  case T::InitCell:
  case T::InitGen:
  case T::Gen:
  case T::Uninit:
  case T::InitNull:
  case T::Bool:
  case T::Int:
  case T::Dbl:
  case T::Res:
  case T::SStr:
  case T::Str:
  case T::Obj:
    return true;

  case T::SVec:
  case T::Vec:
  case T::OptSVec:
  case T::OptVec:
  case T::SDict:
  case T::Dict:
  case T::OptSDict:
  case T::OptDict:
  case T::SKeyset:
  case T::Keyset:
  case T::OptSKeyset:
  case T::OptKeyset:
    return true;

  case T::OptSArr:
  case T::OptArr:
  case T::OptSVArr:
  case T::OptVArr:
  case T::OptSDArr:
  case T::OptDArr:
    // Can't currently have array() info.
    return true;

  case T::SArr:
  case T::Arr:
  case T::SVArr:
  case T::VArr:
  case T::SDArr:
  case T::DArr:
    // array id equals to either kInvalidArrayId for null array info, or a
    // regular id. in each case, we just need to compare their id.
    return arrayId() == o.arrayId();

  case T::SubObj:
  case T::ExactObj:
  case T::OptSubObj:
  case T::OptExactObj:
    return clsName() == o.clsName();
  }
  not_reached();
}