Пример #1
0
 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;
 }
Пример #2
0
  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;
  }
Пример #3
0
 public static ByteCodeClass getClassObject(String name) {
   for (ByteCodeClass cls : classes) {
     if (cls.getClsName().equals(name)) {
       return cls;
     }
   }
   return null;
 }
Пример #4
0
 private static ByteCodeClass getClassByName(String name) {
   name = name.replace('/', '_').replace('$', '_');
   for (ByteCodeClass bc : classes) {
     if (bc.getClsName().equals(name)) {
       return bc;
     }
   }
   return null;
 }
Пример #5
0
 private static boolean isMethodUsedByBaseClassOrInterface(BytecodeMethod mtd, ByteCodeClass cls) {
   boolean b = checkMethodUsedByBaseClassOrInterface(mtd, cls.getBaseClassObject());
   if (b) {
     return true;
   }
   for (ByteCodeClass bc : cls.getBaseInterfacesObject()) {
     b = checkMethodUsedByBaseClassOrInterface(mtd, bc);
     if (b) {
       return true;
     }
   }
   return false;
 }
Пример #6
0
 @Override
 public FieldVisitor visitField(
     int access, String name, String desc, String signature, Object value) {
   ByteCodeField fld = new ByteCodeField(clsName, access, name, desc, signature, value);
   cls.addField(fld);
   return new FieldVisitorWrapper(super.visitField(access, name, desc, signature, value));
 }
Пример #7
0
 private static void appendClassOffset(ByteCodeClass bc, List<Integer> clsIds) {
   if (bc.getBaseClassObject() != null) {
     if (!clsIds.contains(bc.getBaseClassObject().getClassOffset())) {
       clsIds.add(bc.getBaseClassObject().getClassOffset());
       appendClassOffset(bc.getBaseClassObject(), clsIds);
     }
   }
   if (bc.getBaseInterfacesObject() != null) {
     for (ByteCodeClass c : bc.getBaseInterfacesObject()) {
       if (c != null && !clsIds.contains(c.getClassOffset())) {
         clsIds.add(c.getClassOffset());
         if (c.getBaseClassObject() != null) {
           appendClassOffset(c, clsIds);
         }
       }
     }
   }
 }
Пример #8
0
  private static void usedByNativeCheck() {
    for (ByteCodeClass bc : classes) {
      // java_lang_Thread_runImpl___long
      for (BytecodeMethod mtd : bc.getMethods()) {
        // check native code
        StringBuilder b = new StringBuilder();
        mtd.appendFunctionPointer(b);
        String str = b.toString();

        for (String s : nativeSources) {
          if (s.contains(str)) {
            mtd.setUsedByNative(true);
            break;
          }
        }
      }
    }
  }
Пример #9
0
 private static void cullClasses(boolean found, int depth) {
   if (found && depth < 3) {
     for (ByteCodeClass bc : classes) {
       bc.updateAllDependencies();
     }
     // int classCount = classes.size();
     ByteCodeClass.markDependencies(classes);
     List<ByteCodeClass> tmp = ByteCodeClass.clearUnmarked(classes);
     /*if(ByteCodeTranslator.verbose) {
     System.out.println("Classes removed from: " + classCount + " to " + classes.size());
     for(ByteCodeClass bc : classes) {
     if(!tmp.contains(bc)) {
     System.out.println("Removed class: " + bc.getClsName());
     }
     }
     }*/
     classes = tmp;
     eliminateUnusedMethods(depth + 1);
   }
 }
Пример #10
0
  private static void writeFile(
      ByteCodeClass cls, File outputDir, ConcatenatingFileOutputStream writeBufferInstead)
      throws Exception {
    OutputStream outMain =
        writeBufferInstead != null
                && ByteCodeTranslator.output == ByteCodeTranslator.OutputType.OUTPUT_TYPE_IOS
            ? writeBufferInstead
            : new FileOutputStream(
                new File(
                    outputDir, cls.getClsName() + "." + ByteCodeTranslator.output.extension()));

    if (outMain instanceof ConcatenatingFileOutputStream) {
      ((ConcatenatingFileOutputStream) outMain).beginNextFile(cls.getClsName());
    }
    if (ByteCodeTranslator.output == ByteCodeTranslator.OutputType.OUTPUT_TYPE_IOS) {
      outMain.write(cls.generateCCode(classes).getBytes());
      outMain.close();

      // we also need to write the header file for iOS
      String headerName = cls.getClsName() + ".h";
      FileOutputStream outHeader = new FileOutputStream(new File(outputDir, headerName));
      outHeader.write(cls.generateCHeader().getBytes());
      outHeader.close();
    } else {
      outMain.write(cls.generateCSharpCode().getBytes());
      outMain.close();
    }
  }
Пример #11
0
 @Override
 public void visit(
     int version,
     int access,
     String name,
     String signature,
     String superName,
     String[] interfaces) {
   if (name.indexOf("DynaCCSmsServiceConstants") > -1) {
     System.out.println("Break");
   }
   cls.setBaseClass(superName);
   cls.setBaseInterfaces(interfaces);
   if ((access & Opcodes.ACC_ABSTRACT) == Opcodes.ACC_ABSTRACT) {
     cls.setIsAbstract(true);
   }
   if ((access & Opcodes.ACC_INTERFACE) == Opcodes.ACC_INTERFACE) {
     cls.setIsInterface(true);
   }
   if ((access & Opcodes.ACC_FINAL) == Opcodes.ACC_FINAL) {
     cls.setFinalClass(true);
   }
   super.visit(version, access, name, signature, superName, interfaces);
 }
Пример #12
0
  private static boolean isMethodUsed(BytecodeMethod m) {
    for (ByteCodeClass bc : classes) {
      for (BytecodeMethod mtd : bc.getMethods()) {
        if (mtd.isEliminated() || mtd == m) {
          continue;
        }
        if (mtd.isMethodUsed(m)) {
          return true;
        }
      }
    }

    // check native code
    StringBuilder b = new StringBuilder();
    m.appendFunctionPointer(b);
    String str = b.toString();
    for (String s : nativeSources) {
      if (s.contains(str)) {
        return true;
      }
    }

    return false;
  }
Пример #13
0
 @Override
 public MethodVisitor visitMethod(
     int access, String name, String desc, String signature, String[] exceptions) {
   BytecodeMethod mtd = new BytecodeMethod(clsName, access, name, desc, signature, exceptions);
   cls.addMethod(mtd);
   JSRInlinerAdapter a =
       new JSRInlinerAdapter(
           new MethodVisitorWrapper(
               super.visitMethod(access, name, desc, signature, exceptions), mtd),
           access,
           name,
           desc,
           signature,
           exceptions);
   return a;
 }
Пример #14
0
 @Override
 public void visitSource(String source, String debug) {
   cls.setSourceFile(source);
   super.visitSource(source, debug);
 }
Пример #15
0
  public static void writeOutput(File outputDirectory) throws Exception {
    System.out.println("outputDirectory is: " + outputDirectory.getAbsolutePath());
    if (ByteCodeClass.getMainClass() == null) {
      System.out.println(
          "Error main class is not defined. The main class name is expected to have a public static void main(String[]) method and it is assumed to reside in the com.package.name directory");
      System.exit(1);
    }
    String file = "Unknown File";
    try {
      for (ByteCodeClass bc : classes) {
        // special case for object
        if (bc.getClsName().equals("java_lang_Object")) {
          continue;
        }
        file = bc.getClsName();
        bc.setBaseClassObject(getClassByName(bc.getBaseClass()));
        List<ByteCodeClass> lst = new ArrayList<ByteCodeClass>();
        for (String s : bc.getBaseInterfaces()) {
          ByteCodeClass bcode = getClassByName(s);
          if (bcode == null) {
            System.out.println(
                "Error while working with the class: "
                    + s
                    + " file:"
                    + file
                    + " no class definition");
          } else {
            lst.add(getClassByName(s));
          }
        }
        bc.setBaseInterfacesObject(lst);
      }
      for (ByteCodeClass bc : classes) {
        file = bc.getClsName();
        bc.updateAllDependencies();
      }
      ByteCodeClass.markDependencies(classes);
      classes = ByteCodeClass.clearUnmarked(classes);

      // load the native sources (including user native code)
      readNativeFiles(outputDirectory);

      // loop over methods and start eliminating the body of unused methods
      eliminateUnusedMethods();

      generateClassAndMethodIndexHeader(outputDirectory);

      boolean concatenate = "true".equals(System.getProperty("concatenateFiles", "false"));
      ConcatenatingFileOutputStream cos =
          concatenate ? new ConcatenatingFileOutputStream(outputDirectory) : null;

      for (ByteCodeClass bc : classes) {
        file = bc.getClsName();
        writeFile(bc, outputDirectory, cos);
      }
      if (cos != null) cos.realClose();

    } catch (Throwable t) {
      System.out.println("Error while working with the class: " + file);
      t.printStackTrace();
      if (t instanceof Exception) {
        throw (Exception) t;
      }
      if (t instanceof RuntimeException) {
        throw (RuntimeException) t;
      }
    }
  }
Пример #16
0
  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();
  }