示例#1
0
ExnTreeInfo build_exn_tree(const FuncEmitter& fe,
                           php::Func& func,
                           FindBlock findBlock) {
  ExnTreeInfo ret;

  uint32_t nextExnNode = 0;

  for (auto& eh : fe.ehtab()) {
    auto node = folly::make_unique<php::ExnNode>();
    node->id = nextExnNode++;
    node->parent = nullptr;

    switch (eh.m_type) {
    case EHEnt::Type::Fault:
      {
        auto const fault = findBlock(eh.m_fault);
        assert(ret.funcletNodes[fault] == nullptr);
        ret.funcletNodes[fault] = borrow(node);

        /*
         * We know the block for this offset starts a fault funclet,
         * but we won't know its extents until we've built the cfg and
         * can look at the control flow in the funclet.  Set the block
         * type to Fault for now, but we won't propagate the value to
         * the rest of the funclet blocks until find_fault_funclets.
         */
        fault->kind = php::Block::Kind::Fault;
        node->info = php::FaultRegion { fault, eh.m_iterId, eh.m_itRef };
      }
      break;
    case EHEnt::Type::Catch:
      {
        auto treg = php::TryRegion {};
        for (auto& centry : eh.m_catches) {
          auto const catchBlk = findBlock(centry.second);
          catchBlk->kind = php::Block::Kind::CatchEntry;
          treg.catches.emplace_back(
            fe.ue().lookupLitstr(centry.first),
            catchBlk
          );
        }
        node->info = treg;
      }
      break;
    }

    ret.ehMap[&eh] = borrow(node);

    if (eh.m_parentIndex != -1) {
      auto it = ret.ehMap.find(&fe.ehtab()[eh.m_parentIndex]);
      assert(it != end(ret.ehMap));
      node->parent = it->second;
      it->second->children.emplace_back(std::move(node));
    } else {
      func.exnNodes.emplace_back(std::move(node));
    }
  }

  return ret;
}
示例#2
0
文件: parse.cpp 项目: fmarcos83/hhvm
ExnTreeInfo build_exn_tree(const FuncEmitter& fe,
                           php::Func& func,
                           FindBlock findBlock) {
  ExnTreeInfo ret;
  auto nextExnNode = uint32_t{0};

  for (auto& eh : fe.ehtab()) {
    auto node = folly::make_unique<php::ExnNode>();
    node->id = nextExnNode++;
    node->parent = nullptr;

    switch (eh.m_type) {
    case EHEnt::Type::Fault:
      {
        auto const fault = findBlock(eh.m_fault);
        ret.funcletNodes[fault].push_back(borrow(node));
        ret.faultFuncletStarts.insert(eh.m_fault);
        node->info = php::FaultRegion { fault, eh.m_iterId, eh.m_itRef };
      }
      break;
    case EHEnt::Type::Catch:
      {
        auto treg = php::TryRegion {};
        for (auto& centry : eh.m_catches) {
          auto const catchBlk = findBlock(centry.second);
          treg.catches.emplace_back(
            fe.ue().lookupLitstr(centry.first),
            catchBlk
          );
        }
        node->info = treg;
      }
      break;
    }

    ret.ehMap[&eh] = borrow(node);

    if (eh.m_parentIndex != -1) {
      auto it = ret.ehMap.find(&fe.ehtab()[eh.m_parentIndex]);
      assert(it != end(ret.ehMap));
      node->parent = it->second;
      it->second->children.emplace_back(std::move(node));
    } else {
      func.exnNodes.emplace_back(std::move(node));
    }
  }

  ret.faultFuncletStarts.insert(fe.past());

  return ret;
}
示例#3
0
文件: parse.cpp 项目: fmarcos83/hhvm
void build_cfg(ParseUnitState& puState,
               php::Func& func,
               const FuncEmitter& fe) {
  auto const blockStarts = findBasicBlocks(fe);

  FTRACE(3, "    blocks are at: {}\n",
    [&]() -> std::string {
      using namespace folly::gen;
      return from(blockStarts)
        | eachTo<std::string>()
        | unsplit<std::string>(" ");
    }()
  );

  std::map<Offset,std::unique_ptr<php::Block>> blockMap;
  auto const bc = fe.ue().bc();

  auto findBlock = [&] (Offset off) {
    auto& ptr = blockMap[off];
    if (!ptr) {
      ptr               = folly::make_unique<php::Block>();
      ptr->id           = func.nextBlockId++;
      ptr->section      = php::Block::Section::Main;
      ptr->exnNode      = nullptr;
    }
    return borrow(ptr);
  };

  auto exnTreeInfo = build_exn_tree(fe, func, findBlock);

  for (auto it = begin(blockStarts);
      boost::next(it) != end(blockStarts);
      ++it) {
    auto const block   = findBlock(*it);
    auto const bcStart = bc + *it;
    auto const bcStop  = bc + *boost::next(it);

    if (auto const eh = findEH(fe.ehtab(), *it)) {
      auto it = exnTreeInfo.ehMap.find(eh);
      assert(it != end(exnTreeInfo.ehMap));
      block->exnNode = it->second;
      add_factored_exits(*block, block->exnNode);
    }

    populate_block(puState, fe, func, *block, bcStart, bcStop, findBlock);
  }

  link_entry_points(func, fe, findBlock);
  find_fault_funclets(exnTreeInfo, func, blockStarts, findBlock);

  for (auto& kv : blockMap) {
    func.blocks.emplace_back(std::move(kv.second));
  }
}
示例#4
0
文件: emit.cpp 项目: brucezy/hhvm
void emit_eh_region(FuncEmitter& fe,
                    borrowed_ptr<const EHRegion> region,
                    const BlockInfo& blockInfo,
                    ParentIndexMap& parentIndexMap) {
  // A region on a single empty block.
  if (region->start == region->past) return;

  auto& eh = fe.addEHEnt();
  eh.m_base = region->start;
  eh.m_past = region->past;
  assert(eh.m_past >= eh.m_base);
  assert(eh.m_base != kInvalidOffset && eh.m_past != kInvalidOffset);

  if (region->parent) {
    auto parentIt = parentIndexMap.find(region->parent);
    assert(parentIt != end(parentIndexMap));
    eh.m_parentIndex = parentIt->second;
  } else {
    eh.m_parentIndex = -1;
  }
  parentIndexMap[region] = fe.ehtab().size() - 1;

  match<void>(
    region->node->info,
    [&] (const php::TryRegion& tr) {
      eh.m_type = EHEnt::Type::Catch;
      for (auto& c : tr.catches) {
        eh.m_catches.emplace_back(
          fe.ue().mergeLitstr(c.first),
          blockInfo[c.second->id].offset
        );
      }
      eh.m_fault = kInvalidOffset;
      eh.m_iterId = -1;
      eh.m_itRef = false;
    },
    [&] (const php::FaultRegion& fr) {
      eh.m_type = EHEnt::Type::Fault;
      eh.m_fault = blockInfo[fr.faultEntry->id].offset;
      eh.m_iterId = fr.iterId;
      eh.m_itRef = fr.itRef;
    }
  );
}