std::string Array::to_string() const { if (is_primitive()) { return "< " + element_type->to_string() + " x " + std::to_string(length) + " >"; } else { return "[ " + element_type->to_string() + " x " + std::to_string(length) + " ]"; } }
void remove_unused_fields(Scope& scope, const std::vector<std::string>& remove_members) { std::vector<DexField*> moveable_fields; std::vector<DexClass*> smallscope; uint32_t aflags = ACC_STATIC | ACC_FINAL; for (auto clazz : scope) { bool found = can_delete(clazz); if (!found) { auto name = clazz->get_name()->c_str(); for (const auto& name_prefix : remove_members) { if (strstr(name, name_prefix.c_str()) != nullptr) { found = true; break; } } if (!found) { TRACE(FINALINLINE, 2, "Cannot delete: %s\n", SHOW(clazz)); continue; } } auto sfields = clazz->get_sfields(); for (auto sfield : sfields) { if ((sfield->get_access() & aflags) != aflags) continue; auto value = sfield->get_static_value(); if (value == nullptr && !is_primitive(sfield->get_type())) continue; if (!found && !can_delete(sfield)) continue; moveable_fields.push_back(sfield); smallscope.push_back(clazz); } } sort_unique(smallscope); std::unordered_set<DexField*> field_target = get_field_target(scope, moveable_fields); std::unordered_set<DexField*> dead_fields; for (auto field : moveable_fields) { if (field_target.count(field) == 0) { dead_fields.insert(field); } } TRACE(FINALINLINE, 1, "Removable fields %lu/%lu\n", dead_fields.size(), moveable_fields.size()); TRACE(FINALINLINE, 1, "Unhandled inline %ld\n", unhandled_inline); for (auto clazz : smallscope) { auto& sfields = clazz->get_sfields(); auto iter = sfields.begin(); while (iter != sfields.end()) { auto todel = iter++; if (dead_fields.count(*todel) > 0) { sfields.erase(todel); } } } }
void inline_field_values(Scope& fullscope) { std::unordered_set<DexField*> inline_field; std::unordered_set<DexField*> cheap_inline_field; std::vector<DexClass*> scope; uint32_t aflags = ACC_STATIC | ACC_FINAL; for (auto clazz : fullscope) { std::unordered_map<DexField*, bool> blank_statics; get_sput_in_clinit(clazz, blank_statics); auto sfields = clazz->get_sfields(); for (auto sfield : sfields) { if ((sfield->get_access() & aflags) != aflags) continue; if (blank_statics[sfield]) continue; auto value = sfield->get_static_value(); if (value == nullptr && !is_primitive(sfield->get_type())) { continue; } if (value != nullptr && !value->is_evtype_primitive()) { continue; } uint64_t v = value != nullptr ? value->value() : 0; if ((v & 0xffff) == v || (v & 0xffff0000) == v) { cheap_inline_field.insert(sfield); } inline_field.insert(sfield); scope.push_back(clazz); } } std::vector<std::pair<DexMethod*, DexOpcodeField*>> cheap_rewrites; std::vector<std::pair<DexMethod*, DexOpcodeField*>> simple_rewrites; walk_opcodes( fullscope, [](DexMethod* method) { return true; }, [&](DexMethod* method, DexInstruction* insn) { if (insn->has_fields() && is_sfield_op(insn->opcode())) { auto fieldop = static_cast<DexOpcodeField*>(insn); auto field = resolve_field(fieldop->field(), FieldSearch::Static); if (field == nullptr || !field->is_concrete()) return; if (inline_field.count(field) == 0) return; if (cheap_inline_field.count(field) > 0) { cheap_rewrites.push_back(std::make_pair(method, fieldop)); return; } simple_rewrites.push_back(std::make_pair(method, fieldop)); } }); TRACE(FINALINLINE, 1, "Method Re-writes Cheap %lu Simple %lu\n", cheap_rewrites.size(), simple_rewrites.size()); for (auto cheapcase : cheap_rewrites) { inline_cheap_sget(cheapcase.first, cheapcase.second); } for (auto simplecase : simple_rewrites) { inline_sget(simplecase.first, simplecase.second); } MethodTransform::sync_all(); }
PyObject* JPypeJavaArray::setArraySlice(PyObject* self, PyObject* arg) { TRACE_IN("JPypeJavaArray::setArraySlice") PyObject* arrayObject; int lo = -1; int hi = -1; PyObject* sequence; try { JPyArg::parseTuple(arg, "O!iiO", &PyCapsule_Type, &arrayObject, &lo, &hi, &sequence); JPArray* a = (JPArray*)JPyCObject::asVoidPtr(arrayObject); int length = a->getLength(); if(length == 0) Py_RETURN_NONE; if (lo < 0) lo = length + lo; if (lo < 0) lo = 0; else if (lo > length) lo = length; if (hi < 0) hi = length + hi; if (hi < 0) hi = 0; else if (hi > length) hi = length; if (lo > hi) lo = hi; const JPTypeName& componentName = a->getType()->getObjectType().getComponentName(); const string& name = componentName.getNativeName(); if(is_primitive(name[0])) { // for primitive types, we have fast setters available a->setRange(lo, hi, sequence); } else { // slow wrapped access for non primitive types vector<HostRef*> values; values.reserve(hi - lo); JPCleaner cleaner; for (Py_ssize_t i = 0; i < hi - lo; i++) { HostRef* v = new HostRef(JPySequence::getItem(sequence, i), false); values.push_back(v); cleaner.add(v); } a->setRange(lo, hi, values); } Py_RETURN_NONE; } PY_STANDARD_CATCH return NULL; TRACE_OUT }
sexp eval_application(sexp operator, sexp operands) { if (is_primitive(operator)) return (primitive_C_proc(operator))(operands); if (is_compound(operator)) { sexp body = compound_proc_body(operator); sexp vars = compound_proc_parameters(operator); sexp def_env = compound_proc_environment(operator); sexp object = make_pair(S("begin"), body); sexp env = extend_environment(vars, operands, def_env); return eval_object(object, env); } fprintf(stderr, "Unknown operator type %d\n", operator->type); exit(1); }
void remove_unused_fields(Scope& scope, const std::unordered_set<DexType*>& keep_annos, const std::unordered_set<DexField*>& keep_members) { std::vector<DexField*> moveable_fields; std::vector<DexClass*> smallscope; uint32_t aflags = ACC_STATIC | ACC_FINAL; for (auto clazz : scope) { if (!can_delete(clazz)) { continue; } auto sfields = clazz->get_sfields(); for (auto sfield : sfields) { if ((sfield->get_access() & aflags) != aflags) continue; auto value = sfield->get_static_value(); if (value == nullptr && !is_primitive(sfield->get_type())) continue; if (is_kept_by_annotation(sfield, keep_annos)) continue; if (is_kept_member(sfield, keep_members)) continue; moveable_fields.push_back(sfield); smallscope.push_back(clazz); } } sort_unique(smallscope); std::unordered_set<DexField*> field_target = get_field_target(scope, moveable_fields); std::unordered_set<DexField*> dead_fields; for (auto field : moveable_fields) { if (field_target.count(field) == 0) { dead_fields.insert(field); } } TRACE(FINALINLINE, 1, "Removable fields %lu/%lu\n", dead_fields.size(), moveable_fields.size()); TRACE(FINALINLINE, 1, "Unhandled inline %ld\n", unhandled_inline); for (auto clazz : smallscope) { auto& sfields = clazz->get_sfields(); auto iter = sfields.begin(); while (iter != sfields.end()) { auto todel = iter++; if (dead_fields.count(*todel) > 0) { sfields.erase(todel); } } } }
/* * This returns all the pointer-bearing registers whose pointees :insn will * read from. */ std::vector<uint16_t> object_read_registers(const IRInstruction* insn) { switch (insn->opcode()) { case OPCODE_AGET: case OPCODE_AGET_WIDE: case OPCODE_AGET_BOOLEAN: case OPCODE_AGET_BYTE: case OPCODE_AGET_CHAR: case OPCODE_AGET_SHORT: case OPCODE_AGET_OBJECT: case OPCODE_IGET: case OPCODE_IGET_WIDE: case OPCODE_IGET_BOOLEAN: case OPCODE_IGET_BYTE: case OPCODE_IGET_CHAR: case OPCODE_IGET_SHORT: case OPCODE_IGET_OBJECT: case OPCODE_APUT_OBJECT: case OPCODE_IPUT_OBJECT: case OPCODE_SPUT_OBJECT: case OPCODE_RETURN_OBJECT: return {insn->src(0)}; case OPCODE_INVOKE_SUPER: case OPCODE_INVOKE_DIRECT: case OPCODE_INVOKE_STATIC: case OPCODE_INVOKE_VIRTUAL: case OPCODE_INVOKE_INTERFACE: { std::vector<uint16_t> regs; size_t idx{0}; if (insn->opcode() != OPCODE_INVOKE_STATIC) { // The `this` parameter regs.emplace_back(insn->src(idx++)); } auto callee = insn->get_method(); auto arg_types = callee->get_proto()->get_args()->get_type_list(); for (DexType* arg_type : arg_types) { if (!is_primitive(arg_type)) { regs.emplace_back(insn->src(idx)); } ++idx; } return regs; } default: return {}; } }
PyObject* JPypeJavaArray::getArraySlice(PyObject* self, PyObject* arg) { PyObject* arrayObject; int lo = -1; int hi = -1; try { JPyArg::parseTuple(arg, "O!ii", &PyCapsule_Type, &arrayObject, &lo, &hi); JPArray* a = (JPArray*)JPyCObject::asVoidPtr(arrayObject); int length = a->getLength(); // stolen from jcc, to get nice slice support if (lo < 0) lo = length + lo; if (lo < 0) lo = 0; else if (lo > length) lo = length; if (hi < 0) hi = length + hi; if (hi < 0) hi = 0; else if (hi > length) hi = length; if (lo > hi) lo = hi; const JPTypeName& componentName = a->getType()->getObjectType().getComponentName(); const string& name = componentName.getNativeName(); if(is_primitive(name[0])) { // for primitive types, we have fast sequence generation available return a->getSequenceFromRange(lo, hi); } else { // slow wrapped access for non primitives vector<HostRef*> values = a->getRange(lo, hi); JPCleaner cleaner; PyObject* res = JPySequence::newList((int)values.size()); for (unsigned int i = 0; i < values.size(); i++) { JPySequence::setItem(res, i, (PyObject*)values[i]->data()); cleaner.add(values[i]); } return res; } } PY_STANDARD_CATCH return NULL; }
Type Type::operator * (const Type& t2) const { if (_types.size() == 0) { return t2; } if (t2._types.size() == 0) { return *this; } if (*this == t2) { return *this; } if (is_polymorphic() and t2.is_primitive()) { return Type::any(); } if (t2.is_polymorphic() and is_primitive()) { return Type::any(); } if (is_any()) { return t2; } if (t2.is_any()) { return *this; } // Temporary, to be removed when compatible() is removed if ((is_bool() and t2.is_integer()) or (is_integer() and t2.is_bool())) { return any(); } if (t2.compatible(*this)) { return t2; } if (compatible(t2)) { return *this; } if (is_array() and t2.is_array()) { if (element().is_polymorphic() and t2.element().is_polymorphic()) { return array(any()); } } return Type::any(); }
Cell eval(Cell exp, Cell env) { if (is_self_evaluating(exp)) { return exp; } else if (is_atom(exp)) { return lookup(exp, env); } else if (is_tagged(exp, atom("define"))) { return define(car(cdr(exp)), eval(car(cdr(cdr(exp))), env), env); } else if (is_tagged(exp, atom("set!"))) { return set(car(cdr(exp)), eval(car(cdr(cdr(exp))), env), env); } else if (is_tagged(exp, atom("if"))) { Cell cond = eval(car(cdr(exp)), env); if (is_atom(cond) && is_eq(cond, atom("#f"))) { exp = car(cdr(cdr(cdr(exp)))); } else { exp = car(cdr(cdr(exp))); } return eval(exp, env); } else if (is_tagged(exp, atom("vau"))) { return procedure(exp, env); } else if (is_pair(exp)) { Cell proc = eval(car(exp), env); if (is_primitive(proc)) { return (proc->primitive)(eval_operands(cdr(exp), env)); } else if (is_procedure(proc)) { Cell src = car(proc); Cell e = car(cdr(cdr(src))); Cell para = cons(e, cons(car(cdr(src)), null)); Cell args = cons(env, cons(cdr(exp), null)); Cell body = car(cdr(cdr(cdr(src)))); return eval(body, extend_env(para, args, cdr(proc))); } } fprintf(stderr, "eval illegal state\n"); return atom("#<void>"); }
/************************************************************************** * *N select_feature_class_relate * *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * Purpose: *P * Set up the relationships between features and primitives or between * primitives and features (one way only) for a specified feature class. *E *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * History: *H * Barry Michaels DOS Turbo C *E *************************************************************************/ fcrel_type select_feature_class_relate( int fcnum, library_type *library, char *start_table, char *end_table ) { int storage, cov; vpf_table_type fcs; long int i; char path[255], covpath[255]; position_type p; vpf_relate_struct rcell; fcrel_type fcrel; fcrel.nchain = 0; fcrel.table = NULL; fcrel.relate_list = NULL; cov = library->fc[fcnum].coverage; strcpy(covpath,library->cover[cov].path); rightjust(covpath); sprintf( path, "%sfcs", covpath ); /* Feature Class Schema table */ fcs = vpf_open_table( path, disk, "rb", NULL ); fcrel.relate_list = fcs_relate_list( library->fc[fcnum].name, start_table,end_table, fcs ); if (ll_empty(fcrel.relate_list)) { ll_reset(fcrel.relate_list); displaymessage("ERROR in feature class relationship!", start_table,end_table,NULL); return fcrel; } /* Find the number of tables in the relate chain */ p = ll_first(fcrel.relate_list); fcrel.nchain = 0; while (!ll_end(p)) { fcrel.nchain++; p = ll_next(p); } /* Allow for last table2 */ fcrel.nchain++; fcrel.table = (vpf_table_type *) vpfmalloc((fcrel.nchain+1)* sizeof(vpf_table_type)); for (i=0;i<fcrel.nchain+1;i++) vpf_nullify_table( &(fcrel.table[i]) ); p = ll_first(fcrel.relate_list); for (i=0;i<fcrel.nchain-1;i++) { ll_element(p,&rcell); /** Can't open primitive table - may be several under tile **/ /** directories. Open all others **/ if (!is_primitive(rcell.table1)) { sprintf(path,"%s%s",covpath,rcell.table1); if (is_join(rcell.table1)) storage = ram; else storage = disk; fcrel.table[i] = vpf_open_table(path,(storage_type)storage,"rb",NULL); } if (!ll_end(p)) p = ll_next(p); } /* End of relate chain */ i = fcrel.nchain-1; if (!is_primitive(rcell.table2)) { sprintf(path,"%s%s",covpath,rcell.table2); storage = disk; fcrel.table[i] = vpf_open_table(path,(storage_type)storage,"rb",NULL); } vpf_close_table( &fcs ); return fcrel; }
bool Type::is_boolifiable() const { return is_top() || is_primitive() || is_ref(); }
bool Type::is_compound() const { return is_value() && !is_primitive(); }
bool Type::is_value() const { Class* cls = clazz(); return is_primitive() || is_value_proto() || (cls && cls->proto()->is_value_proto()); }
int is_eval(lisp_object_t proc) { return is_primitive(proc) && eval_proc == primitive_C_proc(proc); }