1 23 24 package org.objectweb.fractal.julia.asm; 25 26 import org.objectweb.fractal.julia.loader.Generated; 27 import org.objectweb.fractal.julia.loader.Loader; 28 import org.objectweb.fractal.julia.loader.Tree; 29 30 import org.objectweb.asm.ClassWriter; 31 import org.objectweb.asm.CodeVisitor; 32 import org.objectweb.asm.Constants; 33 import org.objectweb.asm.Type; 34 35 import java.lang.reflect.Method ; 36 import java.util.ArrayList ; 37 import java.util.Arrays ; 38 import java.util.List ; 39 40 50 51 public abstract class AbstractClassGenerator implements 52 ClassGenerator, 53 Constants 54 { 55 56 59 60 public ClassWriter cw; 61 62 65 66 public String name; 67 68 71 72 public String superClass; 73 74 79 80 public List interfaces; 81 82 85 86 public String parameters; 87 88 91 92 public Loader loader; 93 94 97 98 public ClassLoader classLoader; 99 100 116 117 public byte[] generateClass ( 118 final String name, 119 final Tree args, 120 final Loader loader, 121 final ClassLoader classLoader) throws ClassGenerationException 122 { 123 this.name = name.replace('.', '/'); 124 this.parameters = args.toString(); 125 this.loader = loader; 126 this.classLoader = classLoader; 127 this.cw = new ClassWriter(computeMaxs()); 128 parseArgs(args); 129 generateHeader(); 130 generateConstructor(); 131 generateDefaultMethods(); 132 generateInterfaceMethods(); 133 return cw.toByteArray(); 134 } 135 136 145 146 protected void parseArgs (final Tree args) { 147 superClass = args.getSubTree(1).toString().replace('.', '/'); 148 interfaces = new ArrayList (Arrays.asList(args.getSubTree(2).getSubTrees())); 149 for (int i = 0; i < interfaces.size(); ++i) { 150 interfaces.set(i, interfaces.get(i).toString().replace('.', '/')); 151 } 152 } 153 154 163 164 protected boolean computeMaxs () { 165 return false; 166 } 167 168 173 174 protected void generateHeader () throws ClassGenerationException { 175 int access = ACC_PUBLIC; 176 List itfList = getImplementedInterfaces(); 177 String [] itfs = (String [])itfList.toArray(new String [itfList.size()]); 178 cw.visit(V1_1, access, name, superClass, itfs, getSource()); 179 } 180 181 187 188 protected String getSource () { 189 return "GENERATED"; 190 } 191 192 202 203 protected List getImplementedInterfaces () throws ClassGenerationException { 204 List itfs = new ArrayList (interfaces); 205 itfs.add(Type.getInternalName(Generated.class)); 206 return itfs; 207 } 208 209 216 217 protected void generateConstructor () throws ClassGenerationException { 218 CodeVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); 219 mv.visitVarInsn(ALOAD, 0); 221 mv.visitMethodInsn(INVOKESPECIAL, superClass, "<init>", "()V"); 222 mv.visitInsn(RETURN); 223 mv.visitMaxs(1, 1); 224 } 225 226 234 235 protected void generateDefaultMethods () throws ClassGenerationException { 236 String name = "getFcGeneratorParameters"; 237 String desc = "()Ljava/lang/String;"; 238 CodeVisitor mv = cw.visitMethod(ACC_PUBLIC, name, desc, null, null); 239 mv.visitLdcInsn(parameters); 240 mv.visitInsn(ARETURN); 241 mv.visitMaxs(1, 1); 242 } 243 244 253 254 protected void generateInterfaceMethods () throws ClassGenerationException { 255 List generated = new ArrayList (); 256 for (int i = 0; i < interfaces.size(); ++i) { 257 String s = ((String )interfaces.get(i)).replace('/', '.'); 258 Class itf; 259 try { 260 itf = loader.loadClass(s, classLoader); 261 } catch (ClassNotFoundException e) { 262 throw new ClassGenerationException( 263 e, parameters, "Cannot load the '" + s + "' interface"); 264 } 265 Method [] meths = itf.getMethods(); 266 for (int j = 0; j < meths.length; ++j) { 267 Method meth = meths[j]; 268 String desc = meth.getName() + Type.getMethodDescriptor(meth); 269 if (!generated.contains(desc)) { 270 generateMethod(meth); 271 generated.add(desc); 272 } 273 } 274 } 275 } 276 277 284 285 protected abstract void generateMethod (Method m) 286 throws ClassGenerationException; 287 288 299 300 public static int getOpcodeOffset (final Class type) { 301 if (type == Double.TYPE) { 302 return 3; 303 } else if (type == Float.TYPE) { 304 return 2; 305 } else if (type == Long.TYPE) { 306 return 1; 307 } else if (type.isPrimitive()) { 308 return 0; 309 } 310 return 4; 311 } 312 313 320 321 public static int getSize (final Class type) { 322 return (type == Double.TYPE || type == Long.TYPE ? 2 : 1); 323 } 324 } 325 | Popular Tags |