Exemple #1
0
void MInstrEffects::get(const IRInstruction* inst,
                        const FrameStateMgr& frame,
                        LocalStateHook& hook) {
  // If the base for this instruction is a local address, the helper call might
  // have side effects on the local's value
  auto const base = inst->src(minstrBaseIdx(inst->op()));
  auto const locInstr = base->inst();

  // Right now we require that the address of any affected local is the
  // immediate source of the base tmp.  This isn't actually specified in the ir
  // spec right now but will intend to make it more general soon.
  if (locInstr->op() != LdLocAddr) return;

  auto const locId = locInstr->extra<LdLocAddr>()->locId;
  auto const baseType = frame.localType(locId);

  MInstrEffects effects(inst->op(), baseType.ptr(Ptr::Frame));
  if (effects.baseTypeChanged || effects.baseValChanged) {
    auto const ty = effects.baseType.derefIfPtr();
    if (ty.isBoxed()) {
      hook.setLocalType(locId, Type::BoxedInitCell);
      hook.setBoxedLocalPrediction(locId, ty);
    } else {
      hook.setLocalType(locId, ty);
    }
  }

}
Exemple #2
0
void local_effects(const FrameStateMgr& frameState,
                   const IRInstruction* inst,
                   LocalStateHook& hook) {
  auto killIterLocals = [&](const std::initializer_list<uint32_t>& ids) {
    for (auto id : ids) {
      hook.setLocalValue(id, nullptr);
    }
  };

  switch (inst->op()) {
    case CallBuiltin:
      if (inst->extra<CallBuiltin>()->destroyLocals) hook.clearLocals();
      break;

    case Call:
    case CallArray:
    case ContEnter:
      {
        auto const callDestroysLocals =
          (inst->is(CallArray) && inst->extra<CallArray>()->destroyLocals) ||
          (inst->is(Call) && inst->extra<Call>()->destroyLocals);
        hook.killLocalsForCall(callDestroysLocals);
      }
      break;

    case StRef:
      hook.updateLocalRefPredictions(inst->src(0), inst->src(1));
      break;

    case StLocNT:
    case StLoc:
      hook.setLocalValue(inst->extra<LocalId>()->locId, inst->src(1));
      break;

    case LdLoc:
      hook.setLocalValue(inst->extra<LdLoc>()->locId, inst->dst());
      break;

    case StLocPseudoMain:
      hook.predictLocalType(inst->extra<LocalId>()->locId,
                            inst->src(1)->type());
      break;

    case AssertLoc:
    case GuardLoc:
    case CheckLoc: {
      auto id = inst->extra<LocalId>()->locId;
      if (inst->marker().func()->isPseudoMain()) {
        hook.predictLocalType(id, inst->typeParam());
      } else {
        hook.refineLocalType(id,
                             inst->typeParam(),
                             TypeSource::makeGuard(inst));
      }
      break;
    }

    case HintLocInner:
      hook.setBoxedLocalPrediction(inst->extra<HintLocInner>()->locId,
                                   inst->typeParam());
      break;

    case CheckType:
    case AssertType:
      hook.refineLocalValues(inst->src(0), inst->dst());
      break;

    case IterInitK:
    case WIterInitK:
      // kill the locals to which this instruction stores iter's key and value
      killIterLocals({inst->extra<IterData>()->keyId,
                      inst->extra<IterData>()->valId});
      break;

    case IterInit:
    case WIterInit:
      // kill the local to which this instruction stores iter's value
      killIterLocals({inst->extra<IterData>()->valId});
      break;

    case IterNextK:
    case WIterNextK:
      // kill the locals to which this instruction stores iter's key and value
      killIterLocals({inst->extra<IterData>()->keyId,
                      inst->extra<IterData>()->valId});
      break;

    case IterNext:
    case WIterNext:
      // kill the local to which this instruction stores iter's value
      killIterLocals({inst->extra<IterData>()->valId});
      break;

    case InterpOne:
    case InterpOneCF: {
      auto const& id = *inst->extra<InterpOneData>();
      assert(!id.smashesAllLocals || id.nChangedLocals == 0);
      if (id.smashesAllLocals || inst->marker().func()->isPseudoMain()) {
        hook.clearLocals();
      } else {
        auto it = id.changedLocals;
        auto const end = it + id.nChangedLocals;
        for (; it != end; ++it) {
          auto& loc = *it;
          // If changing the inner type of a boxed local, also drop the
          // information about inner types for any other boxed locals.
          if (loc.type.isBoxed()) hook.dropLocalRefsInnerTypes();
          hook.setLocalType(loc.id, loc.type);
        }
      }
      break;
    }
    default:
      break;
  }

  if (MInstrEffects::supported(inst)) {
    MInstrEffects::get(inst, frameState, hook);
  }
}