示例#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);
}
示例#2
0
DexClass* create_class(const DexType* type,
                       const DexType* super_type,
                       const std::string& pkg_name,
                       std::vector<DexField*> fields,
                       const TypeSet& interfaces,
                       bool with_default_ctor,
                       DexAccessFlags access) {
  DexType* t = const_cast<DexType*>(type);
  always_assert(!pkg_name.empty());
  auto name = std::string(type->get_name()->c_str());
  name = pkg_name + "/" + name.substr(1);
  t->set_name(DexString::make_string(name));
  // Create class.
  ClassCreator creator(t);
  creator.set_access(access);
  always_assert(super_type != nullptr);
  creator.set_super(const_cast<DexType*>(super_type));
  for (const auto& itf : interfaces) {
    creator.add_interface(const_cast<DexType*>(itf));
  }
  for (const auto& field : fields) {
    creator.add_field(field);
  }
  auto cls = creator.create();
  // Keeping type-erasure generated classes from being renamed.
  cls->rstate.set_keep_name();

  if (!with_default_ctor) {
    return cls;
  }
  // Create ctor.
  auto super_ctors = type_class(super_type)->get_ctors();
  for (auto super_ctor : super_ctors) {
    auto mc = new MethodCreator(t,
                                DexString::make_string("<init>"),
                                super_ctor->get_proto(),
                                ACC_PUBLIC | ACC_CONSTRUCTOR);
    // Call to super.<init>
    std::vector<Location> args;
    size_t args_size = super_ctor->get_proto()->get_args()->size();
    for (size_t arg_loc = 0; arg_loc < args_size + 1; ++arg_loc) {
      args.push_back(mc->get_local(arg_loc));
    }
    auto mb = mc->get_main_block();
    mb->invoke(OPCODE_INVOKE_DIRECT, super_ctor, args);
    mb->ret_void();
    auto ctor = mc->create();
    TRACE(TERA, 4, " default ctor created %s\n", SHOW(ctor));
    cls->add_method(ctor);
  }
  return cls;
}