示例#1
0
文件: type.cpp 项目: AojiaoZero/hhvm
Type Type::relaxToGuardable() const {
  auto const ty = unspecialize();

  if (ty.isKnownDataType()) return ty;

  if (ty.subtypeOf(UncountedInit)) return Type::UncountedInit;
  if (ty.subtypeOf(Uncounted)) return Type::Uncounted;
  if (ty.subtypeOf(Cell)) return Type::Cell;
  if (ty.subtypeOf(BoxedCell)) return Type::BoxedCell;
  if (ty.subtypeOf(Gen)) return Type::Gen;
  not_reached();
}
示例#2
0
void cgCheckType(IRLS& env, const IRInstruction* inst) {
  // Note: If you add new supported type checks, you should update
  // negativeCheckType() to indicate whether it is precise or not.
  auto const src = inst->src(0);
  auto const dst = inst->dst();
  auto const srcData = srcLoc(env, inst, 0).reg(0);
  auto const srcType = srcLoc(env, inst, 0).reg(1);

  auto& v = vmain(env);

  auto const doJcc = [&] (ConditionCode cc, Vreg sf) {
    fwdJcc(v, env, ccNegate(cc), sf, inst->taken());
  };

  auto const doMov = [&] {
    auto const dstData = dstLoc(env, inst, 0).reg(0);
    auto const dstType = dstLoc(env, inst, 0).reg(1);

    if (dst->isA(TBool) && !src->isA(TBool)) {
      v << movtqb{srcData, dstData};
    } else {
      v << copy{srcData, dstData};
    }
    if (dstType == InvalidReg) return;
    if (srcType != InvalidReg) {
      v << copy{srcType, dstType};
    } else {
      v << ldimmq{src->type().toDataType(), dstType};
    }
  };

  auto const typeParam = inst->typeParam();

  if (src->isA(typeParam)) {
    // src is the target type or better.  Just define our dst.
    doMov();
    return;
  }
  if (!src->type().maybe(typeParam)) {
    // src is definitely not the target type.  Always jump.
    v << jmp{label(env, inst->taken())};
    return;
  }

  if (srcType != InvalidReg) {
    emitTypeTest(v, env, typeParam, srcType, srcData, v.makeReg(), doJcc);
    doMov();
    return;
  }

  if (src->type() <= TBoxedCell && typeParam <= TBoxedCell) {
    // We should never have specific known Boxed types; those should only be
    // used for hints and predictions.
    always_assert(!(typeParam < TBoxedInitCell));
    doMov();
    return;
  }

  /*
   * See if we're just checking the array kind or object class of a value with
   * a mostly-known type.
   *
   * Important: We don't support typeParam being something like
   * StaticArr=kPackedKind unless the src->type() also already knows its
   * staticness.  We do allow things like CheckType<Arr=Packed> t1:StaticArr,
   * though.  This is why we have to check that the unspecialized type is at
   * least as big as the src->type().
   */
  if (typeParam.isSpecialized() &&
      typeParam.unspecialize() >= src->type()) {
    detail::emitSpecializedTypeTest(v, env, typeParam, srcData,
                                    v.makeReg(), doJcc);
    doMov();
    return;
  }

  /*
   * Since not all of our unions carry a type register, there are some
   * situations with strings and arrays that are neither constantly-foldable
   * nor in the emitTypeTest() code path.
   *
   * We currently actually check their persistent bit here, which will let
   * both static and uncounted strings through.  Also note that
   * CheckType<Uncounted> t1:{Null|Str} doesn't get this treatment currently---
   * the emitTypeTest() path above will only check the type register.
   */
  if (!typeParam.isSpecialized() &&
      typeParam <= TUncounted &&
      src->type().subtypeOfAny(TStr, TArr) &&
      src->type().maybe(typeParam)) {
    assertx(src->type().maybe(TPersistent));

    auto const sf = v.makeReg();
    v << cmplim{0, srcData[FAST_REFCOUNT_OFFSET], sf};
    doJcc(CC_L, sf);
    doMov();
    return;
  }

  always_assert_flog(
    false,
    "Bad src: {} and dst: {} types in '{}'",
    src->type(), typeParam, *inst
  );
}