Пример #1
0
  /** Runs BLOAT on a method. */
  public static void bloatMethod(final MethodEditor m, final BloatContext context) {
    try {
      if (Main.COMPACT_ARRAY_INIT) {
        // Compact the initialization of arrays of the basic types by
        // putting the values of the array into a string in the constant
        // pool. The initialization code is replaced with a loop that
        // loads the array from the string in the constant pool.

        if (Main.TRACE) {
          System.out.println("  Compacting Arrays: " + Main.dateFormat.format(new Date()));
        }

        CompactArrayInitializer.transform(m);

        if (Main.DEBUG) {
          System.out.println("---------- After compaction:");
          m.print(System.out);
          System.out.println("---------- end print");
        }
      }

      FlowGraph cfg; // The control flow graph for a method

      if (Main.TRACE) {
        System.out.println("  Constructing CFG: " + Main.dateFormat.format(new Date()));
      }

      try {
        // Construct the control flow graph for method m
        cfg = new FlowGraph(m);
      } catch (final ClassFormatException ex) {
        System.err.println(ex.getMessage());
        context.release(m.methodInfo());
        return;
      }

      // We separate out initialization since before this the FlowGraph
      // more exactly represents the input program.
      cfg.initialize();

      if (Main.TRACE) {
        System.out.println("  Transforming to SSA: " + Main.dateFormat.format(new Date()));
      }

      SSA.transform(cfg);

      if (FlowGraph.DEBUG) {
        System.out.println("---------- After SSA:");
        cfg.print(System.out);
        System.out.println("---------- end print");
      }

      if (Main.DEBUG) {
        cfg.visit(new VerifyCFG(false));
      }

      if (!Tree.USE_STACK) {
        // Do copy propagation and value numbering first to get rid of
        // all the extra copies inserted for dups. If they're left in,
        // it really slows down value numbering.
        if (Main.PROP) {
          if (Main.DEBUG) {
            System.out.println("-----Before Copy Propagation-----");
          }

          if (Main.TRACE) {
            System.out.println("  Copy propagation: " + Main.dateFormat.format(new Date()));
          }

          final ExprPropagation copy = new ExprPropagation(cfg);
          copy.transform();

          if (Main.DEBUG) {
            cfg.visit(new VerifyCFG(false));
          }

          if (Main.DEBUG) {
            System.out.println("------After Copy Propagation-----");
            cfg.print(System.out);
          }
        }
      }

      DeadCodeElimination dce = null;

      if (Main.DCE) {

        if (Main.TRACE) {
          System.out.println("  Dead Code Elimination: " + Main.dateFormat.format(new Date()));
        }

        if (Main.DEBUG) {
          System.out.println("---Before Dead Code Elimination--");
        }

        dce = new DeadCodeElimination(cfg);
        dce.transform();

        if (Main.DEBUG) {
          cfg.visit(new VerifyCFG(false));
        }

        if (Main.DEBUG) {
          System.out.println("---After Dead Code Elimination---");
          cfg.print(System.out);
        }
      }

      if (Main.INFER) {

        if (Main.DEBUG) {
          System.out.println("---------Doing type inference--------");
        }

        if (Main.TRACE) {
          System.out.println("  Type Inferencing: " + Main.dateFormat.format(new Date()));
        }

        TypeInference.transform(cfg, context.getHierarchy());
      }

      if (Main.NUMBER) {

        if (Main.TRACE) {
          System.out.println("  Value Numbering: " + Main.dateFormat.format(new Date()));
        }

        if (Main.DEBUG) {
          System.out.println("--------Doing value numbering--------");
        }

        (new ValueNumbering()).transform(cfg);
      }

      if (Main.FOLD) {
        if (Main.DEBUG) {
          System.out.println("--------Before Value Folding---------");
        }

        if (Main.TRACE) {
          System.out.println("  Value Folding: " + Main.dateFormat.format(new Date()));
        }

        (new ValueFolding()).transform(cfg);

        if (Main.DEBUG) {
          cfg.visit(new VerifyCFG());
        }

        if (Main.DEBUG) {
          System.out.println("---------After Value Folding---------");
          cfg.print(System.out);
        }
      }

      if (Main.PRE) {
        if (Main.DEBUG) {
          System.out.println("-------------Before SSAPRE-----------");
        }

        if (Main.TRACE) {
          System.out.println("  SSAPRE: " + Main.dateFormat.format(new Date()));
        }

        final SSAPRE pre = new SSAPRE(cfg, context);
        pre.transform();

        if (Main.DEBUG) {
          cfg.visit(new VerifyCFG());
        }

        if (Main.DEBUG) {
          System.out.println("-------------After SSAPRE------------");
          cfg.print(System.out);
        }
      }

      if (Main.FOLD) {
        if (Main.DEBUG) {
          System.out.println("--------Before Value Folding---------");
        }

        if (Main.TRACE) {
          System.out.println("  Value Folding: " + Main.dateFormat.format(new Date()));
        }

        (new ValueFolding()).transform(cfg);

        if (Main.DEBUG) {
          cfg.visit(new VerifyCFG());
        }

        if (Main.DEBUG) {
          System.out.println("---------After Value Folding---------");
          cfg.print(System.out);
        }
      }

      if (Main.PROP) {
        if (Main.DEBUG) {
          System.out.println("-------Before Copy Propagation-------");
        }

        if (Main.TRACE) {
          System.out.println("  Copy Propagation " + Main.dateFormat.format(new Date()));
        }

        final ExprPropagation copy = new ExprPropagation(cfg);
        copy.transform();

        if (Main.DEBUG) {
          cfg.visit(new VerifyCFG());
        }

        if (Main.DEBUG) {
          System.out.println("--------After Copy Propagation-------");
          cfg.print(System.out);
        }
      }

      // make sure we've done at least one thing since the last DCE
      if (Main.DCE && (Main.INFER || Main.NUMBER || Main.FOLD || Main.PRE || Main.PROP)) {
        if (Main.DEBUG) {
          System.out.println("-----Before Dead Code Elimination----");
        }

        if (Main.TRACE) {
          System.out.println("  Dead Code Elimination: " + Main.dateFormat.format(new Date()));
        }

        dce = new DeadCodeElimination(cfg);
        dce.transform();

        if (Main.DEBUG) {
          cfg.visit(new VerifyCFG());
        }

        if (Main.DEBUG) {
          System.out.println("-----After Dead Code Elimination-----");
          cfg.print(System.out);
        }
      }

      if (Main.PERSIST) {
        (new PersistentCheckElimination()).transform(cfg);
      }

      if (Main.DIVA) {
        if (Main.DEBUG) {
          System.out.println("-----Before DIVA------");
        }

        if (Main.TRACE) {
          System.out.println("  DIVA: " + Main.dateFormat.format(new Date()));
        }

        (new InductionVarAnalyzer()).transform(cfg);

        if (Main.DEBUG) {
          System.out.println("-----After DIVA-----");
          cfg.print(System.out);
        }
      }

      /*
       * if (STACK_ALLOC) { if (DEBUG) {
       * System.out.println("------------Before StackPRE----------"); }
       *
       * StackPRE pre = new StackPRE(cfg); pre.transform();
       *
       * if (DEBUG) { cfg.visit(new VerifyCFG()); }
       *
       * if (DEBUG) { System.out.println("------------After
       * StackPRE-----------"); cfg.print(System.out); } }
       */

      // Do the new stack optimization
      if (Main.OPT_STACK_2) {

        if (Main.TRACE) {
          System.out.println("  New stack optimization: " + Main.dateFormat.format(new Date()));
        }

        // generate code without doing liveness or register allocation
        final CodeGenerator codegen = new CodeGenerator(m);
        codegen.replacePhis(cfg);
        m.clearCode2();
        cfg.visit(codegen);
        // do stack optimization on the bytecode

        final StackOpt so = new StackOpt();
        so.transform(m);

        // convert it back to a cfg
        cfg = new FlowGraph(m);
        cfg.initialize();

        // convert it back to SSA
        SSA.transform(cfg);

        // do more dead code elimination (eliminate stores)
        dce = new DeadCodeElimination(cfg);
        dce.transform();
      }

      if (Main.TRACE) {
        System.out.println("  Register allocation: " + Main.dateFormat.format(new Date()));
      }

      if (Main.VERIFY) {
        try {
          cfg.visit(new VerifyCFG());
        } catch (final IllegalArgumentException ee) {
          System.out.println(
              " NOTE: CFG did not verify while "
                  + "bloating "
                  + m.name()
                  + " after all optimizations. Exception: "
                  + ee);
        }
      }

      // We're all done performing optimizations. Let's generate some code
      // and go home.

      // Perform liveness analysis of variables in the method.
      // Assign local variables ("registers") to expression values.
      final Liveness liveness = new Liveness(cfg);
      final RegisterAllocator alloc = new RegisterAllocator(cfg, liveness);

      // Gather information which can be used to optimize use of the stack
      if (CodeGenerator.OPT_STACK) {
        if (Main.TRACE) {
          System.out.println("  Old stack optimization: " + Main.dateFormat.format(new Date()));
        }
        StackOptimizer.optimizeCFG(cfg);
      }

      if (Main.TRACE) {
        System.out.println("  Code Generation: " + Main.dateFormat.format(new Date()));
      }

      // Start the code generation process.
      final CodeGenerator codegen = new CodeGenerator(m);
      codegen.replacePhis(cfg);

      if (Main.DEBUG) {
        System.out.println("After fixing Phis------------------------");
        cfg.print(System.out);
        System.out.println("End print--------------------------------");
      }

      codegen.simplifyControlFlow(cfg);
      codegen.allocReturnAddresses(cfg, alloc);

      if (Main.DEBUG) {
        System.out.println("After removing empty blocks--------------");
        cfg.print(System.out);
        System.out.println("End print--------------------------------");
      }

      // Clear the old contents of the bytecode store and generate new
      // code.
      // Code is generated using a visitor pattern on the CFG.
      m.clearCode();
      cfg.visit(codegen);

      Peephole.transform(m);

      // Commit any changes that have been made to the method
      context.commit(m.methodInfo());

    } catch (final Exception ex99) {
      final String msg =
          "** Exception while optimizing "
              + m.name()
              + m.type()
              + " of class "
              + m.declaringClass().name();
      System.err.println(msg);
      System.err.println(ex99.getMessage());
      ex99.printStackTrace(System.err);
      System.exit(1);
    }
  }
Пример #2
0
  /**
   * Parse the command line. Inserts residency, update, and swizzle checks into the bytecode of the
   * methods of the specified classes.
   */
  public static void main(final String[] args) {
    final ClassFileLoader loader = new ClassFileLoader();
    List classes = new ArrayList(); // Names of classes from command line
    boolean gotdir = false; // Did user specify an output dir?

    for (int i = 0; i < args.length; i++) {
      if (args[i].equals("-v") || args[i].equals("-verbose")) {
        Main.VERBOSE++;
      } else if (args[i].equals("-help")) {
        Main.usage();
      } else if (args[i].equals("-classpath")) {
        if (++i >= args.length) {
          Main.usage();
        }

        final String classpath = args[i];
        loader.setClassPath(classpath);
      } else if (args[i].equals("-skip")) {
        if (++i >= args.length) {
          Main.usage();
        }

        final String pkg = args[i].replace('.', '/');
        Main.SKIP.add(pkg);
      } else if (args[i].equals("-only")) {
        if (++i >= args.length) {
          Main.usage();
        }

        final String pkg = args[i].replace('.', '/');
        Main.ONLY.add(pkg);
      } else if (args[i].equals("-closure")) {
        Main.CLOSURE = true;
      } else if (args[i].equals("-relax-loading")) {
        ClassHierarchy.RELAX = true;
      } else if (args[i].equals("-f")) {
        Main.FORCE = true;
      } else if (args[i].equals("-norc")) {
        Main.RC = false;
      } else if (args[i].equals("-rc")) {
        Main.RC = true;
      } else if (args[i].equals("-nouc")) {
        Main.UC = false;
      } else if (args[i].equals("-uc")) {
        Main.UC = true;
      } else if (args[i].equals("-nosc")) {
        Main.SC = false;
      } else if (args[i].equals("-sc")) {
        Main.SC = true;
      } else if (args[i].startsWith("-")) {
        Main.usage();
      } else if (i == args.length - 1) {
        // Last argument is the name of the outpu directory
        final File f = new File(args[i]);

        if (f.exists() && !f.isDirectory()) {
          System.err.println("No such directory: " + f.getPath());
          System.exit(2);
        }

        loader.setOutputDir(f);
        gotdir = true;
      } else {
        classes.add(args[i]);
      }
    }

    if (!gotdir) {
      Main.usage();
    }

    if (classes.size() == 0) {
      Main.usage();
    }

    if (Main.VERBOSE > 3) {
      ClassFileLoader.DEBUG = true;
      ClassEditor.DEBUG = true;
    }

    boolean errors = false;

    final Iterator iter = classes.iterator();

    // Load each class specified on the command line
    while (iter.hasNext()) {
      final String name = (String) iter.next();

      try {
        loader.loadClass(name);
      } catch (final ClassNotFoundException ex) {
        System.err.println("Couldn't find class: " + ex.getMessage());
        errors = true;
      }
    }

    if (errors) {
      System.exit(1);
    }

    final BloatContext context = new CachingBloatContext(loader, classes, Main.CLOSURE);

    if (!Main.CLOSURE) {
      final Iterator e = classes.iterator();

      while (e.hasNext()) {
        final String name = (String) e.next();
        try {
          final ClassInfo info = loader.loadClass(name);
          Main.decorateClass(context, info);
        } catch (final ClassNotFoundException ex) {
          System.err.println("Couldn't find class: " + ex.getMessage());
          System.exit(1);
        }
      }
    } else {
      classes = null;

      final ClassHierarchy hier = context.getHierarchy();

      final Iterator e = hier.classes().iterator();

      while (e.hasNext()) {
        final Type t = (Type) e.next();

        if (t.isObject()) {
          try {
            final ClassInfo info = loader.loadClass(t.className());
            Main.decorateClass(context, info);
          } catch (final ClassNotFoundException ex) {
            System.err.println("Couldn't find class: " + ex.getMessage());
            System.exit(1);
          }
        }
      }
    }
  }