Beispiel #1
0
DexMethod* create_ctor_or_static_dispatch(
    const Spec& spec,
    const std::map<SwitchIndices, DexMethod*>& indices_to_callee) {
  always_assert(indices_to_callee.size() && spec.overridden_meth == nullptr);
  TRACE(SDIS,
        5,
        "creating dispatch %s.%s for targets of size %d\n",
        SHOW(spec.owner_type),
        spec.name.c_str(),
        indices_to_callee.size());
  auto orig_method = indices_to_callee.begin()->second;
  auto mc = init_method_creator(spec, orig_method);
  auto dispatch_arg_list = spec.proto->get_args();
  auto type_tag_loc =
      mc->get_local(is_static(spec.access_flags) ? dispatch_arg_list->size() - 1
                                                 : dispatch_arg_list->size());
  auto ret_loc = get_return_location(spec, mc);
  auto mb = mc->get_main_block();
  // Set type tag field only when using synthesized type tags.
  // For the external type tag case (GQL), merged ctors take care of that
  // automatically.
  if (save_type_tag_to_field(spec)) {
    mb->iput(spec.type_tag_field, ret_loc, type_tag_loc);
  }

  // Setup switch cases
  // The MethodBlocks are to be initialized by switch_op() based on their
  // corresponding keys in the map.
  std::vector<Location> args = get_args_from(orig_method, mc);
  if (is_single_target_case(spec, indices_to_callee)) {
    invoke_static(spec, args, ret_loc, orig_method, mb);
    mb->ret(spec.proto->get_rtype(), ret_loc);
    return materialize_dispatch(orig_method, mc);
  }

  auto cases = get_switch_cases(indices_to_callee, is_ctor(spec));

  // TODO (zwei): better dispatch? E.g., push down invoke-direct to the super
  // ctor to happen after the switch stmt.
  auto def_block = mb->switch_op(type_tag_loc, cases);
  handle_default_block(spec, indices_to_callee, args, ret_loc, def_block);
  mb->ret(spec.proto->get_rtype(), ret_loc);

  for (auto& case_it : cases) {
    auto case_block = case_it.second;
    always_assert(case_block != nullptr);
    auto callee = indices_to_callee.at(case_it.first);
    always_assert(is_static(callee));
    invoke_static(spec, args, ret_loc, callee, case_block);
  }

  return materialize_dispatch(orig_method, mc);
}
Beispiel #2
0
match_t<IRInstruction, std::tuple<match_t<IRInstruction> > >
  invoke_static() {
    return invoke_static(any<IRInstruction>());
};