コード例 #1
0
ファイル: type-constraint.cpp プロジェクト: AmineCherrai/hhvm
bool TypeConstraint::checkTypeAliasNonObj(const TypedValue* tv) const {
  assert(tv->m_type != KindOfObject); // this checks when tv is not an object
  assert(!isSelf() && !isParent());

  auto p = getTypeAliasOrClassWithAutoload(m_namedEntity, m_typeName);
  auto td = p.first;
  auto c = p.second;

  // Common case is that we actually find the alias:
  if (td) {
    if (td->nullable && tv->m_type == KindOfNull) return true;
    return td->any || equivDataTypes(td->kind, tv->m_type);
  }

  // Otherwise, this isn't a proper type alias, but it *might* be a
  // first-class enum. Check if the type is an enum and check the
  // constraint if it is. We only need to do this when the underlying
  // type is not an object, since only int and string can be enums.
  if (c && isEnum(c)) {
    auto dt = c->enumBaseTy();
    // For an enum, if the underlying type is mixed, we still require
    // it is either an int or a string!
    if (dt) {
      return equivDataTypes(*dt, tv->m_type);
    } else {
      return IS_INT_TYPE(tv->m_type) || IS_STRING_TYPE(tv->m_type);
    }
  }
  return false;
}
コード例 #2
0
ファイル: type-constraint.cpp プロジェクト: bnovoa/hiphop-php
bool
TypeConstraint::checkPrimitive(DataType dt) const {
  assert(m_type.m_dt != KindOfObject);
  assert(dt != KindOfRef);
  if (nullable() && IS_NULL_TYPE(dt)) return true;
  return equivDataTypes(m_type.m_dt, dt);
}
コード例 #3
0
ファイル: type-constraint.cpp プロジェクト: Tintazul/hhvm
bool
TypeConstraint::checkPrimitive(DataType dt) const {
  assert(m_type.dt != KindOfObject);
  assert(dt != KindOfRef);
  if (isNullable() && dt == KindOfNull) return true;
  if (isNumber()) { return IS_INT_TYPE(dt) || IS_DOUBLE_TYPE(dt); }
  return equivDataTypes(m_type.dt, dt);
}
コード例 #4
0
ファイル: type-constraint.cpp プロジェクト: bnovoa/hiphop-php
bool TypeConstraint::checkTypedefNonObj(const TypedValue* tv) const {
  assert(tv->m_type != KindOfObject); // this checks when tv is not an object
  assert(!isSelf() && !isParent());

  auto const td = getTypedefWithAutoload(m_namedEntity, m_typeName);
  if (!td) return false;
  if (td->nullable && IS_NULL_TYPE(tv->m_type)) return true;
  return td->kind == KindOfAny || equivDataTypes(td->kind, tv->m_type);
}
コード例 #5
0
ファイル: type-constraint.cpp プロジェクト: 292388900/hhvm
bool TypeConstraint::checkTypeAliasNonObj(const TypedValue* tv) const {
  assert(tv->m_type != KindOfObject);
  assert(isObject());

  auto p = getTypeAliasOrClassWithAutoload(m_namedEntity, m_typeName);
  auto td = p.first;
  auto c = p.second;

  // Common case is that we actually find the alias:
  if (td) {
    if (td->nullable && tv->m_type == KindOfNull) return true;
    auto result = annotCompat(tv->m_type, td->type,
      td->klass ? td->klass->name() : nullptr);
    switch (result) {
      case AnnotAction::Pass: return true;
      case AnnotAction::Fail: return false;
      case AnnotAction::CallableCheck:
        return is_callable(tvAsCVarRef(tv));
      case AnnotAction::DictCheck:
        return tv->m_data.parr->isDict();
      case AnnotAction::VecCheck:
        return tv->m_data.parr->isVecArray();
      case AnnotAction::ObjectCheck: break;
    }
    assert(result == AnnotAction::ObjectCheck);
    assert(td->type == AnnotType::Object);
    // Fall through to the check below, since this could be a type
    // alias to an enum type
    c = td->klass;
  }

  // Otherwise, this isn't a proper type alias, but it *might* be a
  // first-class enum. Check if the type is an enum and check the
  // constraint if it is. We only need to do this when the underlying
  // type is not an object, since only int and string can be enums.
  if (c && isEnum(c)) {
    auto dt = c->enumBaseTy();
    // For an enum, if the underlying type is mixed, we still require
    // it is either an int or a string!
    if (dt) {
      return equivDataTypes(*dt, tv->m_type);
    } else {
      return isIntType(tv->m_type) || isStringType(tv->m_type);
    }
  }
  return false;
}
コード例 #6
0
ファイル: ir-translator.cpp プロジェクト: evictor/hhvm
void
IRTranslator::translateLtGtOp(const NormalizedInstruction& i) {
  auto const op = i.op();
  assert(op == Op::Lt || op == Op::Lte || op == Op::Gt || op == Op::Gte);

  auto leftType = m_hhbcTrans.topType(1, DataTypeGeneric);
  auto rightType = m_hhbcTrans.topType(0, DataTypeGeneric);
  bool ok = equivDataTypes(leftType.toDataType(), rightType.toDataType()) &&
    leftType.subtypeOfAny(Type::Null, Type::Bool, Type::Int);

  HHIR_UNIMPLEMENTED_WHEN(!ok, LtGtOp);
  switch (op) {
    case Op::Lt  : HHIR_EMIT(Lt);
    case Op::Lte : HHIR_EMIT(Lte);
    case Op::Gt  : HHIR_EMIT(Gt);
    case Op::Gte : HHIR_EMIT(Gte);
    default    : HHIR_UNIMPLEMENTED(LtGtOp);
  }
}
コード例 #7
0
ファイル: type-constraint.cpp プロジェクト: bnovoa/hiphop-php
bool
TypeConstraint::check(const TypedValue* tv, const Func* func) const {
  assert(hasConstraint());

  // This is part of the interpreter runtime; perf matters.
  if (tv->m_type == KindOfRef) {
    tv = tv->m_data.pref->tv();
  }
  if (nullable() && IS_NULL_TYPE(tv->m_type)) return true;

  if (tv->m_type == KindOfObject) {
    if (!isObjectOrTypedef()) return false;
    // Perfect match seems common enough to be worth skipping the hash
    // table lookup.
    if (m_typeName->isame(tv->m_data.pobj->getVMClass()->name())) {
      if (shouldProfile()) Class::profileInstanceOf(m_typeName);
      return true;
    }
    const Class *c = nullptr;
    const bool selfOrParentOrCallable = isSelf() || isParent() || isCallable();
    if (selfOrParentOrCallable) {
      if (isSelf()) {
        selfToClass(func, &c);
      } else if (isParent()) {
        parentToClass(func, &c);
      } else {
        assert(isCallable());
        return f_is_callable(tvAsCVarRef(tv));
      }
    } else {
      // We can't save the Class* since it moves around from request
      // to request.
      assert(m_namedEntity);
      c = Unit::lookupClass(m_namedEntity);
    }
    if (shouldProfile() && c) {
      Class::profileInstanceOf(c->preClass()->name());
    }
    if (c && tv->m_data.pobj->instanceof(c)) {
      return true;
    }
    return !selfOrParentOrCallable && checkTypedefObj(tv);
  }

  if (isObjectOrTypedef()) {
    switch (tv->m_type) {
      case KindOfArray:
        if (interface_supports_array(m_typeName)) {
          return true;
        }
        break;
      case KindOfString:
      case KindOfStaticString:
        if (interface_supports_string(m_typeName)) {
          return true;
        }
        break;
      case KindOfInt64:
        if (interface_supports_int(m_typeName)) {
          return true;
        }
        break;
      case KindOfDouble:
        if (interface_supports_double(m_typeName)) {
          return true;
        }
        break;
      default:
        break;
    }

    if (isCallable()) {
      return f_is_callable(tvAsCVarRef(tv));
    }
    return isPrecise() && checkTypedefNonObj(tv);
  }

  return equivDataTypes(m_type.m_dt, tv->m_type);
}
コード例 #8
0
ファイル: type-constraint.cpp プロジェクト: AmineCherrai/hhvm
bool TypeConstraint::check(TypedValue* tv, const Func* func) const {
  assert(hasConstraint());

  // This is part of the interpreter runtime; perf matters.
  if (tv->m_type == KindOfRef) {
    tv = tv->m_data.pref->tv();
  }
  if (isNullable() && tv->m_type == KindOfNull) return true;

  if (isNumber()) {
    return IS_INT_TYPE(tv->m_type) || IS_DOUBLE_TYPE(tv->m_type);
  }

  if (isArrayKey()) {
    return IS_INT_TYPE(tv->m_type) || IS_STRING_TYPE(tv->m_type);
  }

  if (tv->m_type == KindOfObject) {
    if (!isObjectOrTypeAlias()) return false;
    // Perfect match seems common enough to be worth skipping the hash
    // table lookup.
    if (m_typeName->isame(tv->m_data.pobj->getVMClass()->name())) {
      if (isProfileRequest()) InstanceBits::profile(m_typeName);
      return true;
    }
    const Class *c = nullptr;
    const bool selfOrParentOrCallable = isSelf() || isParent() || isCallable();
    if (selfOrParentOrCallable) {
      if (isSelf()) {
        selfToClass(func, &c);
      } else if (isParent()) {
        parentToClass(func, &c);
      } else {
        assert(isCallable());
        return HHVM_FN(is_callable)(tvAsCVarRef(tv));
      }
    } else {
      // We can't save the Class* since it moves around from request
      // to request.
      assert(m_namedEntity);
      c = Unit::lookupClass(m_namedEntity);
    }
    if (isProfileRequest() && c) {
      InstanceBits::profile(c->preClass()->name());
    }
    if (c && tv->m_data.pobj->instanceof(c)) {
      return true;
    }
    return !selfOrParentOrCallable && checkTypeAliasObj(tv);
  }

  if (isObjectOrTypeAlias()) {
    do {
      switch (tv->m_type) {
        case KindOfInt64:
          if (interface_supports_int(m_typeName)) {
            return true;
          }
          continue;

        case KindOfDouble:
          if (interface_supports_double(m_typeName)) {
            return true;
          }
          continue;

        case KindOfStaticString:
        case KindOfString:
          if (interface_supports_string(m_typeName)) {
            return true;
          }
          continue;

        case KindOfArray:
          if (interface_supports_array(m_typeName)) {
            return true;
          }
          continue;

        case KindOfUninit:
        case KindOfNull:
        case KindOfBoolean:
        case KindOfObject:
        case KindOfResource:
          continue;

        case KindOfRef:
        case KindOfClass:
          break;
      }
      not_reached();
    } while (0);

    if (isCallable()) {
      return HHVM_FN(is_callable)(tvAsCVarRef(tv));
    }
    return isPrecise() && checkTypeAliasNonObj(tv);
  }

  return m_type.dt && equivDataTypes(*m_type.dt, tv->m_type);
}