void MethodCreator::forward_method_to(DexMethod* meth, DexMethod* smeth) { auto code = meth->get_code(); if (code != nullptr) { meth->set_code(nullptr); delete code; } MethodCreator mc(meth); MethodBlock* block = mc.get_main_block(); std::vector<Location> args; auto proto = smeth->get_proto(); auto rtype = proto->get_rtype(); auto meth_args = proto->get_args(); if (meth_args != nullptr) { uint16_t arg_count = static_cast<uint16_t>(meth_args->get_type_list().size()); for (auto i = 0; i < arg_count; ++i) { args.push_back(mc.get_local(i)); } } block->invoke(smeth, args); if (rtype == get_void_type()) { block->ret_void(); } else { auto ret = mc.make_local(rtype); block->move_result(ret, rtype); block->ret(ret); } mc.create(); }
DexProto* DexIdx::get_protoidx_fromdex(uint32_t pidx) { redex_assert(pidx < m_proto_ids_size); DexType* rtype = get_typeidx(m_proto_ids[pidx].rtypeidx); DexString* shorty = get_stringidx(m_proto_ids[pidx].shortyidx); DexTypeList* args = get_type_list(m_proto_ids[pidx].param_off); return DexProto::make_proto(rtype, args, shorty); }
uint16_t MethodCreator::ins_count() const { auto proto = method->get_proto(); auto args = proto->get_args(); uint16_t ins = args == nullptr ? 0 : static_cast<uint16_t>(args->get_type_list().size()); if (!(access & ACC_STATIC)) ins++; return ins; }
TypeListComboBox::TypeListComboBox(const uint16_t gen, QWidget* parent): QComboBox(parent) { std::vector<pkstring> types_vec; get_type_list(types_vec, gen); for(uint16_t i = 0; i < types_vec.size(); i++) addItem(QString::fromUtf16(types_vec[i]), QVariant(i)); }
bool check_cast(const DexType* type, const DexType* base_type) { if (type == base_type) return true; const auto cls = type_class(type); if (cls == nullptr) return false; if (check_cast(cls->get_super_class(), base_type)) return true; auto intfs = cls->get_interfaces(); for (auto intf : intfs->get_type_list()) { if (check_cast(intf, base_type)) return true; } return false; }
void MethodCreator::load_locals(DexMethod* meth) { if (!(access & ACC_STATIC)) { make_local(meth->get_class()); } auto proto = meth->get_proto(); auto args = proto->get_args(); if (args) { for (auto arg : args->get_type_list()) { make_local(arg); } } }
void MethodCreator::load_locals(DexMethod* meth) { auto ii = InstructionIterable( meth->get_code()->get_param_instructions()); auto it = ii.begin(); if (!is_static(meth)) { make_local_at(meth->get_class(), it->insn->dest()); ++it; } auto proto = meth->get_proto(); auto args = proto->get_args(); if (args) { for (auto arg : args->get_type_list()) { make_local_at(arg, it->insn->dest()); ++it; } } always_assert(it == ii.end()); }
/** * If the caller is in the primary DEX we want to make sure there are no * references in other DEXes that may cause a verification error. * Don't inline if so. */ bool MultiMethodInliner::refs_not_in_primary(DexMethod* callee) { const auto ok_from_primary = [&](DexType* type) { if (primary.count(type) == 0 && type_class_internal(type) != nullptr) { info.not_in_primary++; return false; } return true; }; for (auto insn : callee->get_code()->get_instructions()) { if (insn->has_types()) { auto top = static_cast<DexOpcodeType*>(insn); if (!ok_from_primary(top->get_type())) { return true; } } else if (insn->has_methods()) { auto mop = static_cast<DexOpcodeMethod*>(insn); auto meth = mop->get_method(); if (!ok_from_primary(meth->get_class())) { return true; } auto proto = meth->get_proto(); if (!ok_from_primary(proto->get_rtype())) { return true; } auto args = proto->get_args(); if (args == nullptr) continue; for (const auto& arg : args->get_type_list()) { if (!ok_from_primary(arg)) { return true; } } } else if (insn->has_fields()) { auto fop = static_cast<DexOpcodeField*>(insn); auto field = fop->field(); if (!ok_from_primary(field->get_class()) || !ok_from_primary(field->get_type())) { return true; } } } return false; }
/** * Move all single impl in a single impl method signature to next pass. * We make a single optimization per pass over any given single impl so * I1, I2 and void I1.m(I2) * the first optimization (I1 or I2) moves the other interface to next pass. * That is not the case for methods on non optimizable classes, so for * I1, I2 and void C.m(I1, I2) * then m is changed in a single pass for both I1 and I2. */ void OptimizationImpl::drop_single_impl_collision(DexType* intf, SingleImplData& data, DexMethod* method) { auto check_type = [&](DexType* type) { if (type != intf && single_impls->is_single_impl(type) && !single_impls->is_escaped(type)) { single_impls->escape_interface(type, NEXT_PASS); assert(optimized.find(type) == optimized.end()); } }; auto owner = method->get_class(); if (!single_impls->is_single_impl(owner)) return; check_type(owner); auto proto = method->get_proto(); check_type(proto->get_rtype()); auto args_list = proto->get_args(); for (auto arg : args_list->get_type_list()) { check_type(arg); } }