service/method-inliner/CFGInliner.cpp
/*
 * Add a throw edge from each may_throw to each catch that is thrown to from the
 * callsite
 *   * If there are already throw edges in callee, add this edge to the end
 *     of the list
 *
 * Assumption: caller_catches is sorted by catch index
 */
Add a throw edge from each may_throw to each catch that is thrown to from the
callsite
If there are already throw edges in callee, add this edge to the end
of the list

caller_catches is sorted by catch index
Add a throw edge from each may_throw to each catch that is thrown to from the callsite If there are already throw edges in callee add this edge to the end of the list caller_catches is sorted by catch index
void CFGInliner::add_callee_throws_to_caller(
    ControlFlowGraph* cfg,
    const std::vector<Block*>& callee_blocks,
    const std::vector<Edge*>& caller_catches) {
  const auto& add_throw_edges =
      [&cfg, &caller_catches](Block* callee_block, uint32_t starting_index) {
        auto index = starting_index;
        for (Edge* caller_catch : caller_catches) {
          cfg->add_edge(callee_block, caller_catch->target(),
                        caller_catch->throw_info()->catch_type, index);
          ++index;
        }
      };
  for (Block* callee_block : callee_blocks) {
    const auto& existing_throws = callee_block->get_outgoing_throws_in_order();
    if (existing_throws.empty()) {
      IRList::iterator last = callee_block->get_last_insn();
      if (last != callee_block->end()) {
        const auto op = last->insn->opcode();
        if (opcode::can_throw(op)) {
          add_throw_edges(callee_block,  0);
        }
      }
    } else if (existing_throws.back()->throw_info()->catch_type != nullptr) {
      add_throw_edges(callee_block,
                      existing_throws.back()->throw_info()->index + 1);
    }
  }
}
void CFGInliner :: add_callee_throws_to_caller ( ControlFlowGraph * cfg , const std :: vector < Block * > & callee_blocks , const std :: vector < Edge * > & caller_catches ) { const auto & add_throw_edges = [ & cfg , & caller_catches ] ( Block * callee_block , uint32_t starting_index ) { auto index = starting_index ; for ( Edge * caller_catch : caller_catches ) { cfg -> add_edge ( callee_block , caller_catch -> target ( ) , caller_catch -> throw_info ( ) -> catch_type , index ) ; ++ index ; } } ; for ( Block * callee_block : callee_blocks ) { const auto & existing_throws = callee_block -> get_outgoing_throws_in_order ( ) ; if ( existing_throws . empty ( ) ) { IRList :: iterator last = callee_block -> get_last_insn ( ) ; if ( last != callee_block -> end ( ) ) { const auto op = last -> insn -> opcode ( ) ; if ( opcode :: can_throw ( op ) ) { add_throw_edges ( callee_block , 0 ) ; } } } else if ( existing_throws . back ( ) -> throw_info ( ) -> catch_type != nullptr ) { add_throw_edges ( callee_block , existing_throws . back ( ) -> throw_info ( ) -> index + 1 ) ; } } }
Add a throw edge from each may_throw to each catch that is thrown to from the
 callsite
   * If there are already throw edges in callee, add this edge to the end
     of the list
Add a throw edge from each may_throw to each catch that is thrown to from the callsite * If there are already throw edges in callee add this edge to the end of the list
// There are two requirements about the catch indices here: //   1) New throw edges must be added to the end of a callee's existing throw //   chain. This is ensured by using the max index of the already existing //   throws //   2) New throw edges must go to the callsite's catch blocks in the same //   order that the existing catch chain does. This is ensured by sorting //   caller_catches by their throw indices. // Add throw edges from callee_block to all the caller catches // Blocks that end in a throwing instruction but don't have outgoing throw // instructions yet. //   * Instructions that can throw that were not in a try region before //   being inlined. These may have been created by split_on_callee_throws. //   * OPCODE_THROW instructions without any catch blocks before being //   inlined. /* starting_index */ // Blocks that throw already //   * Instructions that can throw that were already in a try region with //   catch blocks //   * But don't add to the end of a throw list if there's a catchall //   already