Re: ASM4 / Java 7

Eliot Moss <[email protected]>
Newsgroups gmane.comp.java.objectweb.asm
Message-ID <[email protected]>
Jeremy -- I think you're talking about the need to compute
the common superclass of two classes. I wrote some code
to do that. It uses a static table to remember some facts
about classes that our rewriting agent sees, and so will
have what it needs to know about the superclasses. It does
not need to *load* the classes, only to have seen them
come by the transformer, and superclasses are always seen
before the subclasses.

Most of the code of the class I attach is relevant; the
visitMethod method may not be for you.

Maybe there are more elegant ways to do this, but it seems
to work for the cases we have run so far.

Best wishes -- Eliot Moss
ETPreprocessor.java (text/x-java, 4 KB)
package classReWriter;

import org.objectweb.asm.*;
import org.objectweb.asm.commons.*;
import java.io.*;
import java.util.*;
import java.lang.System;

public class ETPreprocessor extends ClassAdapter {
	
  public static final Map<String,String> superclassOf = new HashMap<String,String>();

  public static final Map<String,Set<String>> superinterfacesOf =
    new HashMap<String,Set<String>>();

  public static final Set<String> interfaces = new HashSet<String>();

  public static final Map<String,Integer> depthOf = new HashMap<String,Integer>();

  public ETPreprocessor (ClassVisitor cv) {
    super(cv);
  }
	
  @Override
  public void visit (int version, int access, String name, String signature,
                     String supername, String[] interfaces) {
    super.visit(version, access, name, signature, supername, interfaces);
    if (name.equals("java/lang/Object")) {
      return;
    }
    if ((access & Opcodes.ACC_INTERFACE) != 0) {
      this.interfaces.add(name);
    }
    superclassOf.put(name, supername);
    Set<String> intfs = new HashSet<String>(2 * interfaces.length);
    superinterfacesOf.put(name, intfs);
    for (String intf : interfaces) {
      intfs.add(intf);
      this.interfaces.add(intf);
    }
    depthOf.put(name, computeDepth(name));
  }

  @Override 
  public MethodVisitor visitMethod (int access, String name, String desc,
                                    String signature, String[] exceptions) {
    MethodVisitor writer = cv.visitMethod(access, name, desc, signature, exceptions);
    return new JSRInlinerAdapter(writer, access, name, desc, signature, exceptions);
  }

  public static String commonSuperclass (String c1, String c2) {
    List<String> supers1 = computeSupers(c1);
    List<String> supers2 = computeSupers(c2);
    if (supers1.contains(c2)) {
      return c1;
    }
    if (supers2.contains(c1)) {
      return c2;
    }
    if (interfaces.contains(c1) || interfaces.contains(c2)) {
      return "java/lang/Object";
    }
    while (true) {
      c1 = superclassOf.get(c1);
      if (c1 == null) {
        return "java/lang/Object";
      }
      if (supers2.contains(c1)) {
        return c1;
      }
    }
  }

  private static int computeDepth (String c) {
    if (c == null || c.equals("java/lang/Object")) {
      return 0;
    } else if (depthOf.containsKey(c)) {
      return depthOf.get(c);
    }
    String sc = superclassOf.get(c);
    int depth = computeDepth(sc) + 1;
    Set<String> intfs = superinterfacesOf.get(c);
    if (intfs != null) {
      for (String intf : intfs) {
        int newDepth = computeDepth(intf) + 1;
        if (newDepth > depth) {
          depth = newDepth;
        }
      }
    }
    depthOf.put(c, depth);
    return depth;
  }

  private static List<String> computeSupers (String c) {
    List<String> temp = new ArrayList<String>();
    List<Integer> depth = new ArrayList<Integer>();
    List<String> queue = new LinkedList<String>();
    Set<String> found = new HashSet<String>();
    temp.add(c);
    depth.add(computeDepth(c));
    queue.add(c);
    found.add(c);
    while (!queue.isEmpty()) {
      String next = queue.remove(0);
      String sc = superclassOf.get(next);
      if (sc == null) {
        sc = "java/lang/Object";
      }
      if (!found.contains(sc)) {
        temp.add(sc);
        depth.add(computeDepth(sc));
        queue.add(sc);
        found.add(sc);
      }
      Set<String> intfs = superinterfacesOf.get(next);
      if (intfs != null) {
        for (String intf : intfs) {
          if (!found.contains(intf)) {
            temp.add(intf);
            depth.add(computeDepth(intf));
            queue.add(intf);
            found.add(intf);
          }
        }
      }
    }
    List<String> result = new ArrayList<String>(temp.size());
    int maxDepth = depth.get(0);
    for (int d = maxDepth; d >= 0; --d) {
      for (int i = depth.size(); --i >= 0; ) {
        if (depth.get(i) == d) {
          result.add(temp.get(i));
        }
      }
    }
    return result;
  }

}

// Local Variables:
// mode:Java
// c-basic-offset:2
// indent-tabs-mode:nil
// End:
message-footer.txt (text/plain, 238 B)
-- 
You receive this message as a subscriber of the [email protected] mailing list.
To unsubscribe: mailto:[email protected]
For general help: mailto:[email protected]?subject=help
OW2 mailing lists service home page: http://www.ow2.org/wws
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.