Beispiel #1
0
// If main trace starts with guards, have them generate a patchable jump
// to the anchor trace
static void hoistGuardJumps(Trace* trace, IRFactory* irFactory) {
  Block* guardLabel = nullptr;
  // Check the beginning of the trace for guards
  for (Block* block : trace->getBlocks()) {
    for (IRInstruction& instr : *block) {
      IRInstruction* inst = &instr;
      Opcode opc = inst->getOpcode();
      if (inst->getTaken() &&
          (opc == LdLoc    || opc == LdStack ||
           opc == GuardLoc || opc == GuardStk)) {
        Block* exitLabel = inst->getTaken();
        // Find the GuardFailure's label and confirm this branches there
        if (!guardLabel && exitLabel->getTrace() != trace) {
          auto instIter = exitLabel->skipLabel();
          // Confirm this is a GuardExit
          for (auto it = instIter, end = exitLabel->end(); it != end; ++it) {
            Opcode op = it->getOpcode();
            if (op == Marker) {
              continue;
            }
            if (op == ExitGuardFailure) {
              guardLabel = exitLabel;
            }
            // Do not optimize if other instructions are on exit trace
            break;
          }
        }
        if (exitLabel == guardLabel) {
          inst->setTCA(kIRDirectGuardActive);
          continue;
        }
        return; // terminate search
      }
      if (opc == Marker || opc == DefLabel || opc == DefSP || opc == DefFP ||
          opc == LdStack) {
        continue;
      }
      return; // terminate search
    }
  }
}
Beispiel #2
0
/*
 * Looks for whether the value in tmp was defined by a load, and if
 * so, changes that load into a load that guards on the given
 * type. Returns true if it succeeds.
 */
static bool hoistGuardToLoad(SSATmp* tmp, Type type) {
  IRInstruction* inst = tmp->getInstruction();
  switch (inst->getOpcode()) {
    case Mov:
    case IncRef:
    {
      // if inst is an incref or move, then chase down its src
      if (hoistGuardToLoad(inst->getSrc(0), type)) {
        // guard was successfully attached to a load instruction
        // refine the type of this mov/incref
        // Note: We can also further simplify incref's here if type is not
        // ref-counted
        tmp->setType(type);
        inst->setTypeParam(type);
        return true;
      }
      break;
    }
    case LdLoc:
    case LdStack:
    case LdMem:
    case LdProp:
    case LdRef:
    case LdClsCns:
    {
      if (!inst->getTaken()) {
        // Not a control flow instruction, so can't give it check semantics
        break;
      }
      Type instType = tmp->getType();
      if (instType == Type::Gen ||
          (instType == Type::Cell && !type.isBoxed())) {
        tmp->setType(type);
        inst->setTypeParam(type);
        return true;
      }
      break;
    }
    default:
      break;
  }
  return false;
}