Exemplo n.º 1
0
match_t<DexMethodRef, std::tuple<> > can_be_constructor() {
  return {
    [](const DexMethodRef* meth) {
      return is_constructor(meth);
    }
  };
}
Exemplo n.º 2
0
match_t<DexMethod, std::tuple<> > is_constructor() {
  return {
    [](const DexMethod* meth) {
      return is_constructor(meth);
    }
  };
}
Exemplo n.º 3
0
void
Function::set_construct_destruct(int ftype, bool no_implicit_type_conversion)
{
    m_ftype = ftype;
    Class *pc = class_context();
//if (!is_plain() && pc) fail("must be within class definition");
    if (is_destructor()) {
        if(signature()->size() > 0) fail("destructor cannot be passed parameters");
        pc->destructor(this);
    } else if (is_constructor()) pc->add_constructor(this,no_implicit_type_conversion);
}
Exemplo n.º 4
0
unsigned list_cases_on(vm_obj const & o, buffer<vm_obj> & data) {
    if (is_simple(o)) {
        return 0;
    } else if (is_constructor(o)) {
        data.append(csize(o), cfields(o));
        return 1;
    } else {
        lean_assert(is_external(o));
        if (auto l = dynamic_cast<vm_list<name>*>(to_external(o))) {
            return list_cases_on_core(l->m_val, data);
        } else if (auto l = dynamic_cast<vm_list<expr>*>(to_external(o))) {
            return list_cases_on_core(l->m_val, data);
        } else if (auto l = dynamic_cast<vm_list<level>*>(to_external(o))) {
            return list_cases_on_core(l->m_val, data);
        } else {
            lean_unreachable();
        }
    }
}
Exemplo n.º 5
0
/*
 * There's no "good way" to differentiate blank vs. non-blank
 * finals.  So, we just scan the code in the CL-init.  If
 * it's sput there, then it's a blank.  Lame, agreed, but functional.
 *
 */
void get_sput_in_clinit(DexClass* clazz,
                        std::unordered_map<DexField*, bool>& blank_statics) {
  auto methods = clazz->get_dmethods();
  for (auto method : methods) {
    if (is_clinit(method)) {
      always_assert_log(is_static(method) && is_constructor(method),
          "static constructor doesn't have the proper access bits set\n");
      auto& code = method->get_code();
      auto opcodes = code->get_instructions();
      for (auto opcode : opcodes) {
        if (opcode->has_fields() && is_sput(opcode->opcode())) {
          auto fieldop = static_cast<DexOpcodeField*>(opcode);
          auto field = resolve_field(fieldop->field(), FieldSearch::Static);
          if (field == nullptr || !field->is_concrete()) continue;
          if (field->get_class() != clazz->get_type()) continue;
          blank_statics[field] = true;
        }
      }
    }
  }
}
Exemplo n.º 6
0
void Function::dump(ostream& os)
{
 Signature::set_fun_name(name(),is_constructor(),is_destructor()); 
 os << *signature();
}
Exemplo n.º 7
0
/**
 * Remove any chance for collisions.
 */
void OptimizationImpl::rename_possible_collisions(
    DexType* intf, SingleImplData& data) {

  const auto& rename = [](DexMethodRef* meth, DexString* name) {
    DexMethodSpec spec;
    spec.cls = meth->get_class();
    spec.name = name;
    spec.proto = meth->get_proto();
    meth->change(spec, false);
  };

  TRACE(INTF, 9, "Changing name related to %s\n", SHOW(intf));
  for (const auto& meth : data.methoddefs) {
    if (!can_rename(meth)) {
      TRACE(INTF, 9, "Changing name but cannot rename %s, give up\n",
          SHOW(meth));
      return;
    }
  }

  std::unordered_map<DexString*, DexString*> names;
  const auto new_name = [&](DexString* name) {
    const auto& name_it = names.find(name);
    if (name_it != names.end()) {
      return name_it->second;
    }
    DexString* possible_name = nullptr;
    static std::string sufx("$r");
    static int intf_id = 0;
    while(true) {
      const auto& str = name->str() + sufx + std::to_string(intf_id++);
      possible_name = DexString::get_string(str.c_str());
      if (possible_name == nullptr) {
        possible_name = DexString::make_string(str.c_str());
        break;
      }
    }
    names[name] = possible_name;
    return possible_name;
  };

  for (const auto& meth : data.methoddefs) {
    if (is_constructor(meth)) continue;
    auto name = new_name(meth->get_name());
    TRACE(INTF, 9, "Changing name for %s to %s\n", SHOW(meth), SHOW(name));
    rename(meth, name);
  }
  for (const auto& refs_it : data.methodrefs) {
    if (refs_it.first->is_def()) continue;
    static auto init = DexString::make_string("<init>");
    always_assert(refs_it.first->get_name() != init);
    auto name = new_name(refs_it.first->get_name());
    TRACE(INTF, 9, "Changing name for %s to %s\n",
        SHOW(refs_it.first), SHOW(name));
    if (names.count(refs_it.first->get_name()) == 0) {
      TRACE(INTF, 9, "Changing name on missing method def %s",
          SHOW(refs_it.first));
    }
    rename(refs_it.first, name);
  }
}
Exemplo n.º 8
0
/**
 * Collect all non virtual methods and make all small methods candidates
 * for inlining.
 */
std::unordered_set<DexMethod*> SimpleInlinePass::gather_non_virtual_methods(
    Scope& scope, const std::unordered_set<DexType*>& no_inline) {
  // trace counter
  size_t all_methods = 0;
  size_t direct_methods = 0;
  size_t direct_no_code = 0;
  size_t non_virtual_no_code = 0;
  size_t clinit = 0;
  size_t init = 0;
  size_t static_methods = 0;
  size_t private_methods = 0;
  size_t dont_strip = 0;
  size_t no_inline_anno_count = 0;
  size_t non_virt_dont_strip = 0;
  size_t non_virt_methods = 0;

  // collect all non virtual methods (dmethods and vmethods)
  std::unordered_set<DexMethod*> methods;

  const auto can_inline_method = [&](DexMethod* meth, DexCode* code) {
    if (has_anno(type_class(meth->get_class()), no_inline) ||
        has_anno(meth, no_inline)) {
      no_inline_anno_count++;
      return;
    }
    if (code->get_instructions().size() < SMALL_CODE_SIZE) {
      // always inline small methods even if they are not deletable
      inlinable.insert(meth);
    } else {
      if (!can_delete(meth)) {
        // never inline methods that cannot be deleted
        TRACE(SINL, 4, "cannot_delete: %s\n", SHOW(meth));
        dont_strip++;
      } else {
        methods.insert(meth);
      }
    }
  };

  walk_methods(scope,
      [&](DexMethod* method) {
        all_methods++;
        if (method->is_virtual()) return;

        auto code = method->get_code();
        bool dont_inline = code == nullptr;

        direct_methods++;
        if (code == nullptr) direct_no_code++;
        if (is_constructor(method)) {
          (is_static(method)) ? clinit++ : init++;
          dont_inline = true;
        } else {
          (is_static(method)) ? static_methods++ : private_methods++;
        }

        if (dont_inline) return;

        can_inline_method(method, code);
      });
  if (m_virtual_inline) {
    auto non_virtual = devirtualize(scope);
    non_virt_methods = non_virtual.size();
    for (const auto& vmeth : non_virtual) {
      auto code = vmeth->get_code();
      if (code == nullptr) {
        non_virtual_no_code++;
        continue;
      }
      can_inline_method(vmeth, code);
    }
  }

  TRACE(SINL, 2, "All methods count: %ld\n", all_methods);
  TRACE(SINL, 2, "Direct methods count: %ld\n", direct_methods);
  TRACE(SINL, 2, "Virtual methods count: %ld\n", all_methods - direct_methods);
  TRACE(SINL, 2, "Direct methods no code: %ld\n", direct_no_code);
  TRACE(SINL, 2, "Direct methods with code: %ld\n",
      direct_methods - direct_no_code);
  TRACE(SINL, 2, "Constructors with or without code: %ld\n", init);
  TRACE(SINL, 2, "Static constructors: %ld\n", clinit);
  TRACE(SINL, 2, "Static methods: %ld\n", static_methods);
  TRACE(SINL, 2, "Private methods: %ld\n", private_methods);
  TRACE(SINL, 2, "Virtual methods non virtual count: %ld\n", non_virt_methods);
  TRACE(SINL, 2, "Non virtual no code count: %ld\n", non_virtual_no_code);
  TRACE(SINL, 2, "Non virtual no strip count: %ld\n", non_virt_dont_strip);
  TRACE(SINL, 2, "Small methods: %ld\n", inlinable.size());
  TRACE(SINL, 2, "Don't strip inlinable methods count: %ld\n", dont_strip);
  TRACE(SINL, 2, "Don't inline annotation count: %ld\n", no_inline_anno_count);
  return methods;
}