コード例 #1
0
ファイル: tracebuilder.cpp プロジェクト: CyaLiven/hiphop-php
SSATmp* TraceBuilder::preOptimizeLdLocAddr(IRInstruction* inst) {
  auto const locId = inst->getExtra<LdLocAddr>()->locId;
  if (getLocalType(locId) != Type::None) { // TODO(#2135185)
    inst->setTypeParam(
      Type::mostRefined(getLocalType(locId).ptr(), inst->getTypeParam())
    );
  }
  return nullptr;
}
コード例 #2
0
ファイル: trace-builder.cpp プロジェクト: IMGM/hiphop-php
SSATmp* TraceBuilder::preOptimizeLdLoc(IRInstruction* inst) {
  auto const locId = inst->extra<LdLoc>()->locId;
  if (auto tmp = getLocalValue(locId)) {
    return tmp;
  }
  if (getLocalType(locId) != Type::None) { // TODO(#2135185)
    inst->setTypeParam(
      Type::mostRefined(getLocalType(locId), inst->typeParam())
    );
  }
  return nullptr;
}
コード例 #3
0
ファイル: tracebuilder.cpp プロジェクト: CyaLiven/hiphop-php
SSATmp* TraceBuilder::preOptimizeDecRefLoc(IRInstruction* inst) {
  auto const locId = inst->getExtra<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.
   */
  auto knownType = getLocalType(locId);
  if (knownType.isBoxed()) {
    knownType = Type::BoxedCell;
  }
  if (knownType != Type::None) { // TODO(#2135185)
    inst->setTypeParam(
      Type::mostRefined(knownType, inst->getTypeParam())
    );
  }

  /*
   * If we have the local value in flight, use a DecRef on it instead
   * of doing it in memory.
   */
  if (auto tmp = getLocalValue(locId)) {
    gen(DecRef, tmp);
    inst->convertToNop();
  }

  return nullptr;
}
コード例 #4
0
/*
 * Stores a ref (boxed value) to a local. Also handles unsetting a local.
 */
void TraceBuilder::genBindLoc(uint32_t id,
                              SSATmp* newValue,
                              bool doRefCount /* = true */) {
  Type trackedType = getLocalType(id);
  SSATmp* prevValue = 0;
  if (trackedType == Type::None) {
    if (doRefCount) {
      prevValue = gen(LdLoc, Type::Gen, LocalId(id), m_fpValue);
    }
  } else {
    prevValue = getLocalValue(id);
    assert(prevValue == nullptr || prevValue->type() == trackedType);
    if (prevValue == newValue) {
      // Silent store: local already contains value being stored
      // NewValue needs to be decref'ed
      if (!trackedType.notCounted() && doRefCount) {
        gen(DecRef, prevValue);
      }
      return;
    }
    if (trackedType.maybeCounted() && !prevValue && doRefCount) {
      prevValue = gen(LdLoc, trackedType, LocalId(id), m_fpValue);
    }
  }
  bool genStoreType = true;
  if ((trackedType.isBoxed() && newValue->type().isBoxed()) ||
      (trackedType == newValue->type() && !trackedType.isString())) {
    // no need to store type with local value
    genStoreType = false;
  }
  gen(genStoreType ? StLoc : StLocNT, LocalId(id), m_fpValue, newValue);
  if (trackedType.maybeCounted() && doRefCount) {
    gen(DecRef, prevValue);
  }
}
コード例 #5
0
void TraceBuilder::genDecRefLoc(int id) {
  Type type = getLocalType(id);

  // Don't generate code if type is not refcounted
  if (type != Type::None && type.notCounted()) {
    return;
  }
  type = noneToGen(type);
  // When a parameter goes out of scope, we need to null
  // it out so that debug_backtrace can't capture stale
  // values.
  bool setNull = id < m_curFunc->getValFunc()->numParams();
  SSATmp* val = getLocalValue(id);
  if (val == nullptr && setNull) {
    val = gen(LdLoc, type, LocalId(id), m_fpValue);
  }
  if (val) {
    if (setNull) {
      gen(StLoc, LocalId(id), m_fpValue, genDefUninit());
    }
    gen(DecRef, val);
    return;
  }

  if (type.isBoxed()) {
    // we can't really rely on the types held in the boxed values since
    // aliasing stores may change them. We conservatively set the type
    // of the decref to a boxed cell.
    type = Type::BoxedCell;
  }

  gen(DecRefLoc, type, LocalId(id), m_fpValue);
}
コード例 #6
0
ファイル: trace-builder.cpp プロジェクト: IMGM/hiphop-php
SSATmp* TraceBuilder::preOptimizeAssertLoc(IRInstruction* inst) {
  auto const locId = inst->extra<AssertLoc>()->locId;
  auto const prevType = getLocalType(locId);
  auto const typeParam = inst->typeParam();

  if (!prevType.equals(Type::None) && !typeParam.strictSubtypeOf(prevType)) {
    if (!prevType.subtypeOf(typeParam)) {
      /* Task #2553746
       * This is triggering for a case where the tracked state says the local is
       * InitNull but the AssertLoc says it's Str. */
      static auto const error =
        StringData::GetStaticString("Internal error: static analysis was "
                                    "wrong about a local variable's type.");
      auto* errorInst = m_irFactory.gen(RaiseError, inst->marker(), cns(error));
      inst->become(&m_irFactory, errorInst);

      // It's not a disaster to generate this in unreachable code for
      // now. t2590033.
      if (false) {
        assert_log(false,  [&]{
            IRTrace& mainTrace = trace()->isMain() ? *trace()
                                                   : *(trace()->main());
            return folly::format("\npreOptimizeAssertLoc: prevType: {} "
                                 "typeParam: {}\nin instr: {}\nin trace: {}\n",
                                 prevType.toString(), typeParam.toString(),
                                 inst->toString(), mainTrace.toString()).str();
          });
      }
    } else {
      inst->convertToNop();
    }
  }
  return nullptr;
}
コード例 #7
0
ファイル: tracebuilder.cpp プロジェクト: CyaLiven/hiphop-php
SSATmp* TraceBuilder::preOptimizeAssertLoc(IRInstruction* inst) {
  auto const locId = inst->getExtra<AssertLoc>()->locId;
  auto const prevType = getLocalType(locId);
  auto const typeParam = inst->getTypeParam();

  if (!prevType.equals(Type::None) && !typeParam.strictSubtypeOf(prevType)) {
    assert(prevType.subtypeOf(typeParam));
    inst->convertToNop();
  }
  return nullptr;
}
コード例 #8
0
/*
 * Store a cell value to a local that might be boxed.
 */
SSATmp* TraceBuilder::genStLoc(uint32_t id,
                               SSATmp* newValue,
                               bool doRefCount,
                               bool genStoreType,
                               Trace* exit) {
  assert(!newValue->type().isBoxed());
  /*
   * If prior value of local is a cell, then  re-use genBindLoc.
   * Otherwise, if prior value of local is a ref:
   *
   * prevLocValue = LdLoc<T>{id} fp
   *    prevValue = LdRef [prevLocValue]
   *       newRef = StRef [prevLocValue], newValue
   * DecRef prevValue
   * -- track local value in newRef
   */
  Type trackedType = getLocalType(id);
  assert(trackedType != Type::None);  // tracelet guards guarantee a type
  if (trackedType.notBoxed()) {
    SSATmp* retVal = doRefCount ? gen(IncRef, newValue) : newValue;
    genBindLoc(id, newValue, doRefCount);
    return retVal;
  }
  assert(trackedType.isBoxed());
  SSATmp* prevRef = getLocalValue(id);
  assert(prevRef == nullptr || prevRef->type() == trackedType);
  // prevRef is a ref
  if (prevRef == nullptr) {
    // prevRef = ldLoc
    prevRef = gen(LdLoc, trackedType, LocalId(id), m_fpValue);
  }
  SSATmp* prevValue = nullptr;
  if (doRefCount) {
    assert(exit);
    Type innerType = trackedType.innerType();
    prevValue = gen(LdRef, innerType, exit, prevRef);
  }
  // stref [prevRef] = t1
  Opcode opc = genStoreType ? StRef : StRefNT;
  gen(opc, prevRef, newValue);

  SSATmp* retVal = newValue;
  if (doRefCount) {
    retVal = gen(IncRef, newValue);
    gen(DecRef, prevValue);
  }
  return retVal;
}
コード例 #9
0
/**
 * Returns an SSATmp containing the current value of the given local.
 * This generates a LdLoc instruction if needed.
 *
 * Note: the type of the local must be known already (due to type guards
 *       or assertions).
 */
SSATmp* TraceBuilder::genLdLoc(uint32_t id) {
  SSATmp* tmp = getLocalValue(id);
  if (tmp) {
    return tmp;
  }
  // No prior value for this local is available, so actually generate a LdLoc.
  auto type = getLocalType(id);
  assert(type != Type::None); // tracelet guards guarantee we have a type
  assert(type != Type::Null); // we can get Uninit or InitNull but not both
  if (type.isNull()) {
    tmp = cns(type);
  } else {
    tmp = gen(LdLoc, type, LocalId(id), m_fpValue);
  }
  return tmp;
}
コード例 #10
0
ファイル: tracebuilder.cpp プロジェクト: CyaLiven/hiphop-php
SSATmp* TraceBuilder::preOptimizeStLoc(IRInstruction* inst) {
  auto const curType = getLocalType(inst->getExtra<StLoc>()->locId);
  auto const newType = inst->getSrc(1)->type();

  assert(inst->getTypeParam().equals(Type::None));

  // There's no need to store the type if it's going to be the same
  // KindOfFoo.  We still have to store string types because we don't
  // guard on KindOfStaticString vs. KindOfString.
  auto const bothBoxed = curType.isBoxed() && newType.isBoxed();
  auto const sameUnboxed = curType != Type::None && // TODO(#2135185)
    curType.isKnownDataType() &&
    curType.equals(newType) && !curType.isString();
  if (bothBoxed || sameUnboxed) {
    inst->setOpcode(StLocNT);
  }

  return nullptr;
}
コード例 #11
0
ファイル: tracebuilder.cpp プロジェクト: CyaLiven/hiphop-php
SSATmp* TraceBuilder::preOptimizeGuardLoc(IRInstruction* inst) {
  auto const locId = inst->getExtra<GuardLoc>()->locId;

  if (auto const prevValue = getLocalValue(locId)) {
    return gen(
      GuardType, inst->getTypeParam(), inst->getTaken(), prevValue
    );
  }

  auto const prevType = getLocalType(locId);
  if (prevType != Type::None) {
    // It doesn't make sense to be guarding on something that's deemed
    // to fail.
    assert(prevType == inst->getTypeParam());
    inst->convertToNop();
  }

  return nullptr;
}
コード例 #12
0
ファイル: trace-builder.cpp プロジェクト: IMGM/hiphop-php
SSATmp* TraceBuilder::preOptimizeCheckLoc(IRInstruction* inst) {
  auto const locId = inst->extra<CheckLoc>()->locId;
  Type typeParam = inst->typeParam();

  if (auto const prevValue = getLocalValue(locId)) {
    return gen(CheckType, typeParam, inst->taken(), prevValue);
  }

  auto const prevType = getLocalType(locId);

  if (prevType == Type::None) {
    return nullptr;
  }

  if (prevType.subtypeOf(typeParam)) {
    inst->convertToNop();
  } else {
    //
    // Normally, it doesn't make sense to be checking something that's
    // deemed to fail.  Incompatible boxed types are ok though, since
    // we don't track them precisely, but instead check them at every
    // use.
    //
    // However, in JitPGO mode right now, this pathological case can
    // happen, because profile counters are not accurate and we
    // currently don't analyze Block post-conditions when picking its
    // successors during region selection.  This can lead to
    // incompatible types in blocks selected for the same region.
    //
    if (!typeParam.isBoxed() || !prevType.isBoxed()) {
      if ((typeParam & prevType) == Type::Bottom) {
        assert(RuntimeOption::EvalJitPGO);
        return gen(Jmp_, inst->taken());
      }
    }
  }

  return nullptr;
}
コード例 #13
0
SSATmp* TraceBuilder::genLdLocAddr(uint32_t id) {
  return gen(LdLocAddr, getLocalType(id).ptr(), LocalId(id), getFp());
}