コード例 #1
0
ファイル: region-hot-cfg.cpp プロジェクト: anthonyattard/hhvm
RegionDescPtr selectHotCFG(HotTransContext& ctx,
                           TransIDSet& selectedSet,
                           TransIDVec* selectedVec /* = nullptr */) {
  ITRACE(1, "selectHotCFG: starting with maxBCInstrs = {}\n", ctx.maxBCInstrs);
  auto const region =
    DFS(ctx.profData, *ctx.cfg, selectedSet, selectedVec, ctx.maxBCInstrs,
        ctx.inlining)
      .formRegion(ctx.tid);

  if (region->empty()) return nullptr;

  ITRACE(3, "selectHotCFG: before region_prune_arcs:\n{}\n",
         show(*region));
  region_prune_arcs(*region, ctx.inputTypes);
  ITRACE(3, "selectHotCFG: before chainRetransBlocks:\n{}\n",
         show(*region));
  region->chainRetransBlocks();

  // Relax the region guards.
  if (RuntimeOption::EvalRegionRelaxGuards) {
    ITRACE(3, "selectHotCFG: before optimizeProfiledGuards:\n{}\n",
           show(*region));
    optimizeProfiledGuards(*region, *ctx.profData);
  }
  ITRACE(1, "selectHotCFG: final version after optimizeProfiledGuards:\n{}\n",
         show(*region));
  return region;
}
void VideoDecoderVP8::updateFormatInfo(vbp_data_vp8 *data) {
    uint32_t width = data->codec_data->frame_width;
    uint32_t height = data->codec_data->frame_height;
    ITRACE("updateFormatInfo: current size: %d x %d, new size: %d x %d",
            mVideoFormatInfo.width, mVideoFormatInfo.height, width, height);

    if ((mVideoFormatInfo.width != width ||
            mVideoFormatInfo.height != height) &&
            width && height) {
        if ((VideoDecoderBase::alignMB(mVideoFormatInfo.width) != width) ||
            (VideoDecoderBase::alignMB(mVideoFormatInfo.height) != height)) {
            mSizeChanged = true;
            ITRACE("Video size is changed.");
        }
        mVideoFormatInfo.width = width;
        mVideoFormatInfo.height = height;
    }

    mVideoFormatInfo.cropLeft = data->codec_data->crop_left;
    mVideoFormatInfo.cropRight = data->codec_data->crop_right;
    mVideoFormatInfo.cropTop = data->codec_data->crop_top;
    mVideoFormatInfo.cropBottom = data->codec_data->crop_bottom;
    ITRACE("Cropping: left = %d, top = %d, right = %d, bottom = %d", data->codec_data->crop_left, data->codec_data->crop_top, data->codec_data->crop_right, data->codec_data->crop_bottom);

    mVideoFormatInfo.valid = true;

    setRenderRect();
}
コード例 #3
0
ファイル: recycle-tc.cpp プロジェクト: Mr-Kumar-Abhishek/hhvm
void reclaimFunction(const Func* func) {
  BlockingLeaseHolder writer(Translator::WriteLease());

  auto it = s_funcTCData.find(func);
  if (it == s_funcTCData.end()) return;

  ITRACE(1, "Tearing down func {} (id={})\n",
         func->fullName()->data(), func->getFuncId());

  Trace::Indent _i;

  auto& data = it->second;
  auto& us = mcg->ustubs();

  ITRACE(1, "Smashing prologues\n");
  clobberFuncGuards(func);

  for (auto& caller : data.callers) {
    ITRACE(1, "Unsmashing call @ {} (guard = {})\n",
           caller.first, caller.second.isGuard);

    // It should be impossible to reach a prologue that has been reclaimed
    // through an immutable stub, as this would imply the function is still
    // reachable.
    auto addr = caller.second.isGuard ? us.bindCallStub
                                      : nullptr;
    smashCall(caller.first, addr);
    s_smashedCalls.erase(caller.first);
  }

  auto movedData = folly::makeMoveWrapper(std::move(data));
  auto fname = func->fullName()->data();
  auto fid   = func->getFuncId();
  // We just smashed all of those callers-- treadmill the free to avoid a
  // race (threads executing callers may end up inside the guard even though
  // the function is now unreachable). Once the following block runs the guards
  // should be unreachable.
  Treadmill::enqueue([fname, fid, movedData] {
    BlockingLeaseHolder writer(Translator::WriteLease());

    ITRACE(1, "Reclaiming func {} (id={})\n", fname, fid);
    Trace::Indent _i;
    {
      ITRACE(1, "Reclaiming Prologues\n");
      Trace::Indent _i;
      for (auto& loc : movedData->prologues) {
        reclaimTranslation(loc);
      }
    }

    for (auto* rec : movedData->srcRecs) {
      reclaimSrcRec(rec);
    }
  });

  s_funcTCData.erase(it);
}
コード例 #4
0
ファイル: region-tracelet.cpp プロジェクト: barnardm/hhvm
/*
 * Records any type/reffiness predictions we depend on in the region. Guards
 * for locals and stack cells that are not used will be eliminated by the call
 * to relaxGuards.
 */
void RegionFormer::recordDependencies() {
  // Record the incrementally constructed reffiness predictions.
  assertx(!m_region->empty());
  auto& frontBlock = *m_region->blocks().front();
  for (auto const& dep : m_refDeps.m_arMap) {
    frontBlock.addReffinessPred(m_startSk, {dep.second.m_mask,
                                            dep.second.m_vals,
                                            dep.first});
  }

  // Relax guards and record the ones that survived.
  auto& firstBlock = *m_region->blocks().front();
  auto blockStart = firstBlock.start();
  auto& unit = m_irgs.unit;
  auto const doRelax = RuntimeOption::EvalHHIRRelaxGuards;
  bool changed = false;
  if (doRelax) {
    Timer _t(Timer::selectTracelet_relaxGuards);
    // The IR is going to be discarded immediately, so skip reflowing
    // the types in relaxGuards to save JIT time.
    RelaxGuardsFlags flags = m_profiling ? RelaxSimple : RelaxNormal;
    changed = relaxGuards(unit, *m_irgs.irb->guards(), flags);
  }

  auto guardMap = std::map<RegionDesc::Location,Type>{};
  ITRACE(2, "Visiting guards\n");
  visitGuards(unit, [&](const RegionDesc::Location& loc, Type type) {
    Trace::Indent indent;
    ITRACE(3, "{}: {}\n", show(loc), type);
    if (type <= TCls) return;
    auto inret = guardMap.insert(std::make_pair(loc, type));
    if (inret.second) return;
    auto& oldTy = inret.first->second;
    if (oldTy == TGen) {
      // This is the case that we see an inner type prediction for a GuardLoc
      // that got relaxed to Gen.
      return;
    }
    oldTy &= type;
  });

  for (auto& kv : guardMap) {
    if (kv.second == TGen) {
      // Guard was relaxed to Gen---don't record it.
      continue;
    }
    auto const preCond = RegionDesc::TypedLocation { kv.first, kv.second };
    ITRACE(1, "selectTracelet adding guard {}\n", show(preCond));
    firstBlock.addPreCondition(blockStart, preCond);
  }

  if (changed) {
    printUnit(3, unit, " after guard relaxation ", nullptr,
              m_irgs.irb->guards());
  }

}
コード例 #5
0
ファイル: recycle-tc.cpp プロジェクト: Mr-Kumar-Abhishek/hhvm
void reclaimTranslation(TransLoc loc) {
  BlockingLeaseHolder writer(Translator::WriteLease());

  ITRACE(1, "Reclaiming translation M[{}, {}] C[{}, {}] F[{}, {}]\n",
         loc.mainStart(), loc.mainEnd(), loc.coldStart(), loc.coldEnd(),
         loc.frozenStart(), loc.frozenEnd());

  Trace::Indent _i;

  auto& cache = mcg->code();
  cache.blockFor(loc.mainStart()).free(loc.mainStart(), loc.mainSize());
  cache.blockFor(loc.coldStart()).free(loc.coldStart(), loc.coldSize());
  if (loc.coldStart() != loc.frozenStart()) {
    cache.blockFor(loc.frozenStart()).free(loc.frozenStart(), loc.frozenSize());
  }

  for (auto it = s_smashedBranches.begin(); it != s_smashedBranches.end();) {
    auto br = it++;
    if (loc.contains(br->first)) {
      ITRACE(1, "Erasing smashed branch @ {} from SrcRec addr={}\n",
             br->first, (void*)br->second);
      br->second->removeIncomingBranch(br->first);
      s_smashedBranches.erase(br);
    }
  }

  // Erase meta-data about these regions of the TC
  {
    ITRACE(1, "Clearing translation meta-data\n");
    Trace::Indent _i;
    clearTCMaps(loc.mainStart(), loc.mainEnd());
    clearTCMaps(loc.coldCodeStart(), loc.coldEnd());
    clearTCMaps(loc.frozenCodeStart(), loc.frozenEnd());
  }

  if (debug) {
    // Ensure no one calls into the function
    ITRACE(1, "Overwriting function\n");
    auto clearBlock = [] (CodeBlock& cb) {
      X64Assembler a {cb};
      while (cb.available() >= 2) a.ud2();
      if (cb.available() > 0) a.int3();
      always_assert(!cb.available());
    };

    CodeBlock main, cold, frozen;
    main.init(loc.mainStart(), loc.mainSize(), "Dead Main");
    cold.init(loc.coldStart(), loc.coldSize(), "Dead Cold");
    frozen.init(loc.frozenStart(), loc.frozenSize(), "Dead Frozen");

    clearBlock(main);
    clearBlock(cold);
    clearBlock(frozen);
  }
}
コード例 #6
0
ファイル: frame-state.cpp プロジェクト: Paul-ReferralMob/hhvm
/*
 * Save current state for block.  If this is the first time saving state for
 * block, create a new snapshot.  Otherwise merge the current state into the
 * existing snapshot.
 */
void FrameState::save(Block* block) {
  ITRACE(4, "Saving state for B{}: {}\n", block->id(), show(*this));
  auto it = m_snapshots.find(block);
  if (it != m_snapshots.end()) {
    merge(it->second);
    ITRACE(4, "Merged state: {}\n", show(*this));
  } else {
    auto& snapshot = m_snapshots[block] = createSnapshot();
    snapshot.inlineSavedStates = m_inlineSavedStates;
  }
}
コード例 #7
0
ファイル: unwind.cpp プロジェクト: jmarrama/hhvm
UnwindAction checkHandlers(const EHEnt* eh,
                           const ActRec* const fp,
                           PC& pc,
                           Fault& fault) {
  auto const func = fp->m_func;
  ITRACE(1, "checkHandlers: func {} ({})\n",
         func->fullName()->data(),
         func->unit()->filepath()->data());

  for (int i = 0;; ++i) {
    // Skip the initial m_handledCount - 1 handlers that were
    // considered before.
    if (fault.m_handledCount <= i) {
      fault.m_handledCount++;
      switch (eh->m_type) {
      case EHEnt::Type::Fault:
        ITRACE(1, "checkHandlers: entering fault at {}: save {}\n",
               eh->m_fault,
               func->unit()->offsetOf(pc));
        pc = func->unit()->entry() + eh->m_fault;
        DEBUGGER_ATTACHED_ONLY(phpDebuggerExceptionHandlerHook());
        return UnwindAction::ResumeVM;
      case EHEnt::Type::Catch:
        // Note: we skip catch clauses if we have a pending C++ exception
        // as part of our efforts to avoid running more PHP code in the
        // face of such exceptions.
        if (ThreadInfo::s_threadInfo->m_pendingException == nullptr) {
          auto const obj = fault.m_userException;
          for (auto& idOff : eh->m_catches) {
            ITRACE(1, "checkHandlers: catch candidate {}\n", idOff.second);
            auto handler = func->unit()->at(idOff.second);
            auto const cls = Unit::lookupClass(
              func->unit()->lookupNamedEntityId(idOff.first)
            );
            if (!cls || !obj->instanceof(cls)) continue;

            ITRACE(1, "checkHandlers: entering catch at {}\n", idOff.second);
            pc = handler;
            DEBUGGER_ATTACHED_ONLY(phpDebuggerExceptionHandlerHook());
            return UnwindAction::ResumeVM;
          }
        }
        break;
      }
    }
    if (eh->m_parentIndex != -1) {
      eh = &func->ehtab()[eh->m_parentIndex];
    } else {
      break;
    }
  }
  return UnwindAction::Propagate;
}
コード例 #8
0
ファイル: guard-constraint.cpp プロジェクト: swtaarrs/hhvm
GuardConstraint relaxConstraint(GuardConstraint origGc,
                                Type knownType, Type toRelax) {
  ITRACE(4, "relaxConstraint({}, knownType = {}, toRelax = {})\n",
         origGc, knownType, toRelax);
  Trace::Indent _i;

  // AssertType can be given TCtx, which should never relax.
  if (toRelax.maybe(TCctx)) {
    always_assert(toRelax <= TCtx);
    return origGc;
  }

  auto const dstType = knownType & toRelax;
  always_assert_flog(typeFitsConstraint(dstType, origGc),
                     "refine({}, {}) doesn't fit {}",
                     knownType, toRelax, origGc);

  // Preserve origGc's weak property.
  GuardConstraint newGc{DataTypeGeneric};
  newGc.weak = origGc.weak;

  while (true) {
    if (newGc.isSpecialized()) {
      // We need to ask for the right kind of specialization, so grab it from
      // origGc.
      if (origGc.wantArrayKind()) newGc.setWantArrayKind();
      if (origGc.wantClass()) newGc.setDesiredClass(origGc.desiredClass());
    }

    auto const relaxed = relaxType(toRelax, newGc.category);
    auto const newDstType = relaxed & knownType;
    if (typeFitsConstraint(newDstType, origGc)) break;

    ITRACE(5, "newDstType = {}, newGc = {}; incrementing constraint\n",
      newDstType, newGc);
    incCategory(newGc.category);
  }
  // DataTypeCountness can be relaxed to DataTypeGeneric in
  // optimizeProfiledGuards, so we can't rely on this category to give type
  // information through guards.  Since relaxConstraint is used to relax the
  // DataTypeCategory for guards, we cannot return DataTypeCountness unless we
  // already had it to start with.  Instead, we return DataTypeBoxCountness,
  // which won't be further relaxed by optimizeProfiledGuards.
  if (newGc.category == DataTypeCountness && origGc != DataTypeCountness) {
    newGc.category = DataTypeBoxAndCountness;
  }
  ITRACE(4, "Returning {}\n", newGc);
  // newGc shouldn't be any more specific than origGc.
  always_assert(newGc.category <= origGc.category);
  return newGc;
}
コード例 #9
0
bool UeventObserver::threadLoop()
{
    if (mUeventFd == -1) {
        ETRACE("invalid uEvent file descriptor");
        return false;
    }

    struct pollfd fds[2];
    int nr;

    fds[0].fd = mUeventFd;
    fds[0].events = POLLIN;
    fds[0].revents = 0;
    fds[1].fd = mExitRDFd;
    fds[1].events = POLLIN;
    fds[1].revents = 0;
    nr = poll(fds, 2, -1);

    if (nr > 0 && fds[0].revents == POLLIN) {
        int count = recv(mUeventFd, mUeventMessage, UEVENT_MSG_LEN - 2, 0);
        if (count > 0) {
            onUevent();
        }
    } else if (fds[1].revents) {
        close(mExitRDFd);
        mExitRDFd = -1;
        ITRACE("exiting wait");
        return false;
    }
    // always looping
    return true;
}
コード例 #10
0
ファイル: ext_libxml.cpp プロジェクト: KOgames/hhvm
static req::ptr<File> libxml_streams_IO_open_wrapper(
    const char *filename, const char* mode, bool read_only)
{
  ITRACE(1, "libxml_open_wrapper({}, {}, {})\n", filename, mode, read_only);
  Trace::Indent _i;

  auto strFilename = String::attach(StringData::Make(filename, CopyString));
  /* FIXME: PHP calls stat() here if the wrapper has a non-null stat handler,
   * in order to skip the open of a missing file, thus suppressing warnings.
   * Our stat handlers are virtual, so there's no easy way to tell if stat
   * is supported, so instead we will just call stat() for plain files, since
   * of the default transports, only plain files have support for stat().
   */
  if (read_only) {
    int pathIndex = 0;
    Stream::Wrapper* wrapper = Stream::getWrapperFromURI(strFilename,
                                                         &pathIndex);
    if (dynamic_cast<FileStreamWrapper*>(wrapper)) {
      if (!HHVM_FN(file_exists)(strFilename)) {
        return nullptr;
      }
    }
  }

  // PHP unescapes the URI here, but that should properly be done by the
  // wrapper.  The wrapper should expect a valid URI, e.g. file:///foo%20bar
  return File::Open(strFilename, mode, 0,
                    tl_libxml_request_data->m_streams_context);
}
コード例 #11
0
ファイル: ext_libxml.cpp プロジェクト: KOgames/hhvm
static xmlOutputBufferPtr
libxml_create_output_buffer(const char *URI,
                            xmlCharEncodingHandlerPtr encoder,
                            int compression ATTRIBUTE_UNUSED)
{
  ITRACE(1, "libxml_create_output_buffer({}, {}, {})\n",
         URI, (void*)encoder, compression);
  Trace::Indent _i;

  if (URI == nullptr) {
    return nullptr;
  }
  // PHP unescapes the URI here, but that should properly be done by the
  // wrapper.  The wrapper should expect a valid URI, e.g. file:///foo%20bar
  auto stream = libxml_streams_IO_open_wrapper(URI, "wb", false);
  if (!stream || stream->isInvalid()) {
    return nullptr;
  }
  // Allocate the Output buffer front-end.
  xmlOutputBufferPtr ret = xmlAllocOutputBuffer(encoder);
  if (ret != nullptr) {
    ret->context = rememberStream(std::move(stream));
    ret->writecallback = libxml_streams_IO_write;
    ret->closecallback = libxml_streams_IO_close;
  }

  return ret;
}
コード例 #12
0
ファイル: cfg.cpp プロジェクト: shantanusharma/hhvm
bool removeUnreachable(IRUnit& unit) {
  ITRACE(2, "removing unreachable blocks\n");
  Trace::Indent _i;

  boost::dynamic_bitset<> visited(unit.numBlocks());
  jit::vector<Block*> blocks;
  jit::vector<Block*> stack;
  blocks.reserve(unit.numBlocks());
  stack.reserve(unit.numBlocks());

  // Find all blocks reachable from the entry block.
  stack.push_back(unit.entry());
  while (!stack.empty()) {
    auto* b = stack.back();
    stack.pop_back();
    if (visited.test(b->id())) continue;
    visited.set(b->id());
    blocks.push_back(b);
    if (auto* taken = b->taken()) {
      if (!visited.test(taken->id())) stack.push_back(taken);
    }
    if (auto* next = b->next()) {
      if (!visited.test(next->id())) stack.push_back(next);
    }
  }

  // Walk through the reachable blocks and erase any preds that weren't
  // found.
  jit::vector<IRInstruction*> deadInsts;
  for (auto* block : blocks) {
    for (auto &edge : block->preds()) {
      auto* inst = edge.inst();
      always_assert(!inst->isTransient());
      if (!visited.test(inst->block()->id())) {
        deadInsts.push_back(inst);
      }
    }
  }

  for (auto* inst : deadInsts) {
    ITRACE(3, "removing unreachable B{}\n", inst->block()->id());
    inst->setNext(nullptr);
    inst->setTaken(nullptr);
  }

  return !deadInsts.empty();
}
コード例 #13
0
ファイル: cfg.cpp プロジェクト: IshanRastogi/hhvm
bool removeUnreachable(IRUnit& unit) {
  ITRACE(2, "removing unreachable blocks\n");
  Trace::Indent _i;

  boost::dynamic_bitset<> visited(unit.numBlocks());
  jit::vector<Block*> blocks;
  jit::vector<Block*> stack;
  blocks.reserve(unit.numBlocks());
  stack.reserve(unit.numBlocks());

  // Find all blocks reachable from the entry block.
  stack.push_back(unit.entry());
  while (!stack.empty()) {
    auto* b = stack.back();
    stack.pop_back();
    if (visited.test(b->id())) continue;
    visited.set(b->id());
    blocks.push_back(b);
    if (auto* taken = b->taken()) {
      if (!visited.test(taken->id())) stack.push_back(taken);
    }
    if (auto* next = b->next()) {
      if (!visited.test(next->id())) stack.push_back(next);
    }
  }

  // Walk through the reachable blocks and erase any preds that weren't
  // found.
  bool modified = false;
  for (auto* block: blocks) {
    auto& preds = block->preds();
    for (auto it = preds.begin(); it != preds.end(); ) {
      auto* inst = it->inst();
      ++it;

      if (!visited.test(inst->block()->id())) {
        ITRACE(3, "removing unreachable B{}\n", inst->block()->id());
        inst->setNext(nullptr);
        inst->setTaken(nullptr);
        modified = true;
      }
    }
  }

  return modified;
}
コード例 #14
0
ファイル: guard-relaxation.cpp プロジェクト: hucy001/hhvm
/*
 * relaxConstraint returns the least specific TypeConstraint 'tc' that doesn't
 * prevent the intersection of knownType and relaxType(toRelax, tc) from
 * satisfying origTc. It is used in IRBuilder::constrainValue and
 * IRBuilder::constrainStack to determine how to constrain the typeParam and
 * src values of CheckType/CheckStk instructions, and the src values of
 * AssertType/AssertStk instructions.
 *
 * AssertType example:
 * t24:Obj<C> = AssertType<{Obj<C>|InitNull}> t4:Obj
 *
 * If constrainValue is called with (t24, DataTypeSpecialized), relaxConstraint
 * will be called with (DataTypeSpecialized, Obj<C>|InitNull, Obj). After a few
 * iterations it will determine that constraining Obj with DataTypeCountness
 * will still allow the result type of the AssertType instruction to satisfy
 * DataTypeSpecialized, because relaxType(Obj, DataTypeCountness) == Obj.
 */
TypeConstraint relaxConstraint(const TypeConstraint origTc,
                               const Type knownType, const Type toRelax) {
  ITRACE(4, "relaxConstraint({}, knownType = {}, toRelax = {})\n",
         origTc, knownType, toRelax);
  Trace::Indent _i;

  auto const dstType = refineType(knownType, toRelax);
  always_assert_flog(typeFitsConstraint(dstType, origTc),
                     "refine({}, {}) doesn't fit {}",
                     knownType, toRelax, origTc);

  // Preserve origTc's weak property.
  TypeConstraint newTc{DataTypeGeneric, DataTypeGeneric};
  newTc.weak = origTc.weak;

  while (true) {
    if (newTc.isSpecialized()) {
      // We need to ask for the right kind of specialization, so grab it from
      // origTc.
      if (origTc.wantArrayKind()) newTc.setWantArrayKind();
      if (origTc.wantClass()) newTc.setDesiredClass(origTc.desiredClass());
    }

    auto const relaxed = relaxType(toRelax, newTc);
    auto const newDstType = refineType(relaxed, knownType);
    if (typeFitsConstraint(newDstType, origTc)) break;

    ITRACE(5, "newDstType = {}, newTc = {}; ", newDstType, newTc);
    if (newTc.category == DataTypeGeneric ||
        !typeFitsOuterConstraint(newDstType, origTc)) {
      FTRACE(5, "incrementing outer\n");
      incCategory(newTc.category);
    } else if (!typeFitsInnerConstraint(newDstType, origTc)) {
      FTRACE(5, "incrementing inner\n");
      incCategory(newTc.innerCat);
    } else {
      not_reached();
    }
  }

  ITRACE(4, "Returning {}\n", newTc);
  // newTc shouldn't be any more specific than origTc.
  always_assert(newTc.category <= origTc.category &&
                newTc.innerCat <= origTc.innerCat);
  return newTc;
}
コード例 #15
0
ファイル: ext_libxml.cpp プロジェクト: KOgames/hhvm
int libxml_streams_IO_write(void* context, const char* buffer, int len) {
  ITRACE(1, "libxml_IO_write({}, {}, {})\n", context, (void*)buffer, len);
  Trace::Indent _i;

  auto stream = getStream(context);
  int64_t ret = stream->write(String(buffer, len, CopyString));
  return (ret < INT_MAX) ? ret : -1;
}
コード例 #16
0
ファイル: frame-state.cpp プロジェクト: Paul-ReferralMob/hhvm
///// Methods for managing and merge block state /////
void FrameState::startBlock(Block* block) {
  auto it = m_snapshots.find(block);
  if (it != m_snapshots.end()) {
    load(it->second);
    ITRACE(4, "Loading state for B{}: {}\n", block->id(), show(*this));
    m_inlineSavedStates = it->second.inlineSavedStates;
    m_snapshots.erase(it);
  }
}
コード例 #17
0
ファイル: cfg.cpp プロジェクト: CodeKong/hhvm
bool removeUnreachable(IRUnit& unit) {
  ITRACE(2, "removing unreachable blocks\n");
  Trace::Indent _i;

  smart::hash_set<Block*, pointer_hash<Block>> visited;
  smart::stack<Block*> stack;
  stack.push(unit.entry());

  // Find all blocks reachable from the entry block.
  while (!stack.empty()) {
    auto* b = stack.top();
    stack.pop();
    if (visited.count(b)) continue;

    visited.insert(b);
    if (auto* taken = b->taken()) {
      if (!visited.count(taken)) stack.push(taken);
    }
    if (auto* next = b->next()) {
      if (!visited.count(next)) stack.push(next);
    }
  }

  // Walk through the reachable blocks and erase any preds that weren't
  // found.
  bool modified = false;
  for (auto* block : visited) {
    auto& preds = block->preds();
    for (auto it = preds.begin(); it != preds.end(); ) {
      auto* inst = it->inst();
      ++it;

      if (!visited.count(inst->block())) {
        ITRACE(3, "removing unreachable B{}\n", inst->block()->id());
        inst->setNext(nullptr);
        inst->setTaken(nullptr);
        modified = true;
      }
    }
  }

  return modified;
}
コード例 #18
0
ファイル: mutation.cpp プロジェクト: bjori/hhvm
void retypeDests(IRInstruction* inst, const IRUnit* unit) {
  for (int i = 0; i < inst->numDsts(); ++i) {
    auto const ssa = inst->dst(i);
    auto const oldType = ssa->type();
    retypeDst(inst, i);
    if (ssa->type() != oldType) {
      ITRACE(5, "reflowTypes: retyped {} in {}\n", oldType.toString(),
             inst->toString());
    }
  }
}
コード例 #19
0
ファイル: frame-state.cpp プロジェクト: Paul-ReferralMob/hhvm
void FrameState::refineLocalType(uint32_t id, Type type, SSATmp* typeSource) {
  always_assert(id < m_locals.size());
  auto& local = m_locals[id];
  Type newType = refineType(local.type, type);
  ITRACE(2, "updating local {}'s type: {} -> {}\n",
         id, local.type, newType);
  always_assert_flog(newType != Type::Bottom,
                     "Bad new type for local {}: {} & {} = {}",
                     id, local.type, type, newType);
  local.type = newType;
  local.typeSource = typeSource;
}
コード例 #20
0
ファイル: ext_libxml.cpp プロジェクト: KOgames/hhvm
int libxml_streams_IO_close(void* context) {
  ITRACE(1, "libxml_IO_close({}), sweeping={}\n",
         context, MemoryManager::sweeping());
  Trace::Indent _i;

  if (MemoryManager::sweeping()) {
    // Stream wrappers close themselves on sweep, so there's nothing to do here
    return 0;
  }

  return forgetStream(context) ? 0 : -1;
}
コード例 #21
0
ファイル: ir-builder.cpp プロジェクト: abhiskaushik/hhvm
bool IRBuilder::constrainLocal(uint32_t locId, SSATmp* typeSrc,
                               TypeConstraint tc,
                               const std::string& why) {
  if (!shouldConstrainGuards()) return false;
  always_assert(IMPLIES(tc.innerCat > DataTypeGeneric,
                        tc.category >= DataTypeCountness));

  ITRACE(1, "constrainLocal({}, {}, {}, {})\n",
         locId, typeSrc ? typeSrc->inst()->toString() : "null", tc, why);
  Indent _i;

  if (!typeSrc) return false;
  if (!typeSrc->isA(Type::FramePtr)) {
    return constrainValue(typeSrc, tc);
  }

  // When typeSrc is a FramePtr, that means we loaded the value the local had
  // coming into the trace. Trace through the FramePtr chain, looking for a
  // guard for this local id. If we find it, constrain the guard. If we don't
  // find it, there wasn't a guard for this local so there's nothing to
  // constrain.
  auto guard = guardForLocal(locId, typeSrc);
  while (guard) {
    if (guard->is(AssertLoc)) {
      // If the refined type of the local satisfies the constraint we're
      // trying to apply, we can stop here. This can happen if we assert a
      // more general type than what we already know. Otherwise we need to
      // keep tracing back to the guard.
      if (typeFitsConstraint(guard->typeParam(), tc)) return false;
      guard = guardForLocal(locId, guard->src(0));
    } else {
      assert(guard->is(GuardLoc, CheckLoc));
      ITRACE(2, "found guard to constrain\n");
      return constrainGuard(guard, tc);
    }
  }

  ITRACE(2, "no guard to constrain\n");
  return false;
}
コード例 #22
0
ファイル: mutation.cpp プロジェクト: DmitrySoshnikov/hhvm
void retypeDests(IRInstruction* inst, const IRUnit* unit) {
  for (int i = 0; i < inst->numDsts(); ++i) {
    auto const ssa = inst->dst(i);
    auto const oldType = ssa->type();
    retypeDst(inst, i);
    if (!ssa->type().equals(oldType)) {
      ITRACE(5, "reflowTypes: retyped {} in {}\n", oldType.toString(),
             inst->toString());
    }
  }

  assert(checkOperandTypes(inst, unit));
}
コード例 #23
0
ファイル: ext_libxml.cpp プロジェクト: Dream-Seeker/hhvm
int libxml_streams_IO_write(void* context, const char* buffer, int len) {
  ITRACE(1, "libxml_IO_write({}, {}, {})\n", context, (void*)buffer, len);
  Trace::Indent _i;

  Resource stream(static_cast<ResourceData*>(context));
  String strBuffer(StringData::Make(buffer, len, CopyString));
  Variant ret = HHVM_FN(fwrite)(stream, strBuffer);
  if (ret.isInteger() && ret.asInt64Val() < INT_MAX) {
    return (int)ret.asInt64Val();
  } else {
    return -1;
  }
}
コード例 #24
0
ファイル: ir-builder.cpp プロジェクト: abhiskaushik/hhvm
/*
 * Returns true iff a guard to constrain was found, and tc was more specific
 * than the guard's existing constraint. Note that this doesn't necessarily
 * mean that the guard was constrained: tc.weak might be true.
 */
bool IRBuilder::constrainGuard(IRInstruction* inst, TypeConstraint tc) {
  if (!shouldConstrainGuards()) return false;

  auto& guard = m_guardConstraints[inst];
  auto changed = false;
  auto const assertFits = typeFitsConstraint(guard.assertedType, tc);
  ITRACE(2, "constrainGuard({}, {}): existing constraint {}, assertFits: {}\n",
         *inst, tc, guard, assertFits ? "true" : "false");
  Indent _i;

  // For category and innerCat, constrain the guard if the assertedType isn't
  // strong enough to fit what we want and tc is more specific than the
  // existing category.

  if (!assertFits && tc.innerCat > guard.innerCat) {
    if (!tc.weak) {
      ITRACE(1, "constraining inner type of {}: {} -> {}\n",
             *inst, guard.innerCat, tc.innerCat);
      guard.innerCat = tc.innerCat;
    }
    changed = true;
  } else {
    ITRACE(2, "not constraining innerCat\n");
  }

  if (!assertFits && tc.category > guard.category) {
    if (!tc.weak) {
      ITRACE(1, "constraining {}: {} -> {}\n",
             *inst, guard.category, tc.category);
      guard.category = tc.category;
    }
    changed = true;
  } else {
    ITRACE(2, "not constraining category\n");
  }

  // It's fairly common to have a local that we've asserted to be Obj, and then
  // later assert that it's Obj<C>|InitNull. We want to use their intersection,
  // so in this case we'd assert Obj<C>.
  always_assert(tc.assertedType.maybe(guard.assertedType));
  auto assertCommon = tc.assertedType & guard.assertedType;
  if (assertCommon < guard.assertedType) {
    // We don't check tc.weak here because assertedType is supposed to be
    // statically known type information.
    ITRACE(1, "using {} to refine assertedType of {}: {} -> {}\n",
           tc.assertedType, *inst, guard.assertedType, assertCommon);
    guard.assertedType = assertCommon;
  } else {
    ITRACE(2, "not refining assertedType\n");
  }

  return changed;
}
コード例 #25
0
ファイル: unwind.cpp プロジェクト: fredemmott/hhvm
UnwindAction checkHandlers(const EHEnt* eh,
                           const ActRec* const fp,
                           PC& pc,
                           Fault& fault) {
  auto const func = fp->m_func;
  ITRACE(1, "checkHandlers: func {} ({})\n",
         func->fullName()->data(),
         func->unit()->filepath()->data());

  for (int i = 0;; ++i) {
    // Skip the initial m_handledCount - 1 handlers that were
    // considered before.
    if (fault.m_handledCount <= i) {
      fault.m_handledCount++;
      switch (eh->m_type) {
      case EHEnt::Type::Fault:
        ITRACE(1, "checkHandlers: entering fault at {}: save {}\n",
               eh->m_handler,
               func->unit()->offsetOf(pc));
        pc = func->unit()->at(eh->m_handler);
        DEBUGGER_ATTACHED_ONLY(phpDebuggerExceptionHandlerHook());
        return UnwindAction::ResumeVM;
      case EHEnt::Type::Catch:
        ITRACE(1, "checkHandlers: entering catch at {}\n", eh->m_handler);
        pc = func->unit()->at(eh->m_handler);
        DEBUGGER_ATTACHED_ONLY(phpDebuggerExceptionHandlerHook());
        return UnwindAction::ResumeVM;
      }
    }
    if (eh->m_parentIndex != -1) {
      eh = &func->ehtab()[eh->m_parentIndex];
    } else {
      break;
    }
  }
  return UnwindAction::Propagate;
}
コード例 #26
0
ファイル: ext_libxml.cpp プロジェクト: KOgames/hhvm
int libxml_streams_IO_read(void* context, char* buffer, int len) {
  ITRACE(1, "libxml_IO_read({}, {}, {})\n", context, (void*)buffer, len);
  Trace::Indent _i;

  auto stream = getStream(context);
  assert(len >= 0);
  if (len > 0) {
    String str = stream->read(len);
    if (str.size() <= len) {
      std::memcpy(buffer, str.data(), str.size());
      return str.size();
    }
  }

  return -1;
}
コード例 #27
0
ファイル: tc-recycle.cpp プロジェクト: HilayPatel/hhvm
/*
 * Reclaim all translations associated with a SrcRec including the anchor
 * translation.
 */
void reclaimSrcRec(const SrcRec* rec) {
  assertOwnsCodeLock();
  assertOwnsMetadataLock();

  ITRACE(1, "Reclaiming SrcRec addr={} anchor={}\n", (void*)rec,
         rec->getFallbackTranslation());

  Trace::Indent _i;

  auto anchor = rec->getFallbackTranslation();
  code().blockFor(anchor).free(anchor, svcreq::stub_size());

  for (auto& loc : rec->translations()) {
    reclaimTranslation(loc);
  }
}
コード例 #28
0
ファイル: ext_libxml.cpp プロジェクト: Dream-Seeker/hhvm
int libxml_streams_IO_read(void* context, char* buffer, int len) {
  ITRACE(1, "libxml_IO_read({}, {}, {})\n", context, (void*)buffer, len);
  Trace::Indent _i;

  Resource stream(static_cast<ResourceData*>(context));
  assert(len >= 0);
  Variant ret = HHVM_FN(fread)(stream, len);
  if (ret.isString()) {
    const String& str = ret.asCStrRef();
    if (str.size() <= len) {
      std::memcpy(buffer, str.data(), str.size());
      return str.size();
    }
  }

  return -1;
}
コード例 #29
0
ファイル: ext_libxml.cpp プロジェクト: Dream-Seeker/hhvm
int libxml_streams_IO_close(void* context) {
  ITRACE(1, "libxml_IO_close({}), sweeping={}\n",
         context, MemoryManager::sweeping());
  Trace::Indent _i;

  if (MemoryManager::sweeping()) {
    // Stream wrappers close themselves on sweep, so there's nothing to do here
    return 0;
  }

  Resource stream(static_cast<ResourceData*>(context));
  // Release the reference owned by context. Guaranteed to not go to zero since
  // we just created one belonging to stream.
  stream.get()->decRefCount();

  return HHVM_FN(fclose)(stream) ? 0 : -1;
}
コード例 #30
0
ファイル: ext_libxml.cpp プロジェクト: KOgames/hhvm
static xmlParserInputPtr libxml_ext_entity_loader(const char *url,
                                                  const char *id,
                                                  xmlParserCtxtPtr context) {
  ITRACE(1, "libxml_ext_entity_loader({}, {}, {})\n",
         url, id, (void*)context);
  Trace::Indent _i;

  auto protocol = Stream::getWrapperProtocol(url);
  if (!allow_ext_entity_protocol(protocol)) {
    raise_warning("Protocol '%s' for external XML entity '%s' is disabled for"
                  " security reasons. This may be changed using the"
                  " hhvm.libxml.ext_entity_whitelist ini setting.",
                  protocol.c_str(), url);
    return nullptr;
  }

  return s_default_entity_loader(url, id, context);
}