private static boolean checkMethodUsedByBaseClassOrInterface( BytecodeMethod mtd, ByteCodeClass cls) { if (cls == null) { return false; } if (cls.getBaseInterfacesObject() != null) { for (ByteCodeClass bc : cls.getBaseInterfacesObject()) { for (BytecodeMethod m : bc.getMethods()) { if (m.getMethodName().equals(mtd.getMethodName())) { if (m.isUsedByNative()) { return true; } break; } } } } for (BytecodeMethod m : cls.getMethods()) { if (m.getMethodName().equals(mtd.getMethodName())) { if (m.isUsedByNative()) { return true; } break; } } return false; }
private static boolean cullMethods(boolean found) { for (ByteCodeClass bc : classes) { bc.unmark(); if (bc.isIsInterface() || bc.getBaseClass() == null) { continue; } for (BytecodeMethod mtd : bc.getMethods()) { if (mtd.isEliminated() || mtd.isUsedByNative() || mtd.isMain() || mtd.getMethodName().equals("__CLINIT__") || mtd.getMethodName().equals("finalize") || mtd.isNative()) { continue; } if (!isMethodUsed(mtd)) { if (isMethodUsedByBaseClassOrInterface(mtd, bc)) { continue; } found = true; mtd.setEliminated(true); /*if(ByteCodeTranslator.verbose) { System.out.println("Eliminating method: " + mtd.getClsName() + "." + mtd.getMethodName()); }*/ } } } return found; }
private static void generateClassAndMethodIndexHeader(File outputDirectory) throws Exception { int classOffset = 0; int methodOffset = 0; ArrayList<BytecodeMethod> methods = new ArrayList<BytecodeMethod>(); for (ByteCodeClass bc : classes) { bc.setClassOffset(classOffset); classOffset++; methodOffset = bc.updateMethodOffsets(methodOffset); methods.addAll(bc.getMethods()); } StringBuilder bld = new StringBuilder(); StringBuilder bldM = new StringBuilder(); bldM.append("#include \"cn1_class_method_index.h\"\n"); bldM.append("#include \"cn1_globals.h\"\n\n"); bld.append("#ifndef __CN1_CLASS_METHOD_INDEX_H__\n#define __CN1_CLASS_METHOD_INDEX_H__\n\n"); bld.append("// maps to offsets in the constant pool below\nextern int classNameLookup[];\n"); bldM.append("// maps to offsets in the constant pool below\nint classNameLookup[] = {"); boolean first = true; for (ByteCodeClass bc : classes) { if (first) { bldM.append("\n "); } else { bldM.append(",\n "); } first = false; bldM.append(addToConstantPool(bc.getClsName().replace('_', '.'))); bldM.append(""); } bldM.append("};\n\n"); for (ByteCodeClass bc : classes) { bld.append("#define cn1_class_id_"); bld.append(bc.getClsName()); bld.append(" "); bld.append(bc.getClassOffset()); bld.append("\n"); } int arrayId = classes.size() + 1; bld.append("#define cn1_array_start_offset "); bld.append(arrayId); bld.append("\n"); // leave space for primitive arrays arrayId += 100; for (ByteCodeClass bc : classes) { bld.append("#define cn1_array_1_id_"); bld.append(bc.getClsName()); bld.append(" "); bld.append(arrayId); bld.append("\n"); arrayId++; bld.append("#define cn1_array_2_id_"); bld.append(bc.getClsName()); bld.append(" "); bld.append(arrayId); bld.append("\n"); arrayId++; bld.append("#define cn1_array_3_id_"); bld.append(bc.getClsName()); bld.append(" "); bld.append(arrayId); bld.append("\n"); arrayId++; /*bld.append("#define cn1_array_4_id_"); bld.append(bc.getClsName()); bld.append(" "); bld.append(arrayId); bld.append("\n"); arrayId++;*/ } bld.append("\n\n"); bld.append("// maps to offsets in the constant pool below\nextern int methodNameLookup[];\n"); bldM.append("// maps to offsets in the constant pool below\nint methodNameLookup[] = {"); first = true; for (BytecodeMethod m : methods) { if (first) { bldM.append("\n "); } else { bldM.append(",\n "); } first = false; bldM.append(addToConstantPool(m.getMethodName())); bldM.append(""); } bldM.append("};\n\n"); ArrayList<Integer> instances = new ArrayList<Integer>(); int counter = 0; for (ByteCodeClass bc : classes) { /*bld.append("extern int classInstanceOfArr"); bld.append(counter); bld.append("[];\n");*/ bldM.append("int classInstanceOfArr"); bldM.append(counter); bldM.append("[] = {"); counter++; appendClassOffset(bc, instances); for (Integer i : instances) { bldM.append(i); bldM.append(", "); } instances.clear(); bldM.append("-1};\n"); } bld.append("extern int *classInstanceOf[];\n"); bldM.append("int *classInstanceOf["); bldM.append(classes.size()); bldM.append("] = {"); first = true; counter = 0; for (ByteCodeClass bc : classes) { if (first) { bldM.append("\n "); } else { bldM.append(",\n "); } first = false; bldM.append("classInstanceOfArr"); bldM.append(counter); counter++; } bldM.append("};\n\n"); bld.append("#define CN1_CONSTANT_POOL_SIZE "); bld.append(constantPool.size()); bld.append("\n\nextern const char * const constantPool[];\n"); bldM.append("\n\nconst char * const constantPool[] = {\n"); first = true; int offset = 0; for (String con : constantPool) { if (first) { bldM.append("\n \""); } else { bldM.append(",\n \""); } first = false; try { bldM.append(encodeString(con)); } catch (Throwable t) { t.printStackTrace(); System.out.println("Error writing the constant pool string: '" + con + "'"); System.exit(1); } bldM.append("\" /* "); bldM.append(offset); offset++; bldM.append(" */"); } bldM.append("};\n\nint classListSize = "); bldM.append(classes.size()); bldM.append(";\n"); for (ByteCodeClass bc : classes) { bldM.append("extern struct clazz class__"); bldM.append(bc.getClsName().replace('/', '_').replace('$', '_')); bldM.append(";\n"); } bldM.append("\n\nstruct clazz* classesList[] = {"); first = true; for (ByteCodeClass bc : classes) { if (first) { bldM.append("\n "); } else { bldM.append(",\n "); } first = false; bldM.append(" &class__"); bldM.append(bc.getClsName().replace('/', '_').replace('$', '_')); } bldM.append("};\n\n\n"); // generate the markStatics method for (ByteCodeClass bc : classes) { bc.appendStaticFieldsExtern(bldM); } bldM.append( "\n\nextern int recursionKey;\nvoid markStatics(CODENAME_ONE_THREAD_STATE) {\n recursionKey++;\n"); for (ByteCodeClass bc : classes) { bc.appendStaticFieldsMark(bldM); } bldM.append("}\n\n"); bld.append("\n\n#endif // __CN1_CLASS_METHOD_INDEX_H__\n"); FileOutputStream fos = new FileOutputStream(new File(outputDirectory, "cn1_class_method_index.h")); fos.write(bld.toString().getBytes("UTF-8")); fos.close(); fos = new FileOutputStream(new File(outputDirectory, "cn1_class_method_index.m")); fos.write(bldM.toString().getBytes("UTF-8")); fos.close(); }