1 23 24 package org.objectweb.fractal.julia.asm; 25 26 import org.objectweb.fractal.julia.InitializationContext; 27 import org.objectweb.fractal.julia.loader.Initializable; 28 import org.objectweb.fractal.julia.loader.Tree; 29 30 import org.objectweb.asm.CodeVisitor; 31 import org.objectweb.asm.Type; 32 33 import java.lang.reflect.Method ; 34 import java.util.ArrayList ; 35 import java.util.List ; 36 37 154 155 public abstract class SimpleCodeGenerator 156 extends AbstractCodeGenerator 157 implements Initializable 158 { 159 160 165 166 private Tree args; 167 168 171 172 private InterceptorClassGenerator icg; 173 174 177 178 private String delegateFieldName; 179 180 183 184 private String delegateFieldDesc; 185 186 189 190 private String owner; 191 192 196 public void initialize (final Tree args) { 197 this.args = args.getSubTree(0); 198 } 199 200 204 public int init (final InterceptorClassGenerator icg) { 205 this.icg = icg; 206 return IN; 207 } 208 209 public void generateInitCode (final CodeVisitor cv) 210 throws ClassGenerationException 211 { 212 String owner = null; 215 for (int i = 0; i < icg.controllerClasses.length; ++i) { 216 Class c = icg.controllerClasses[i]; 217 List params = new ArrayList (); 218 if (needsInterfaceName()) { 219 params.add(String .class); 220 } 221 if (needsTargetObject()) { 222 params.add(Object .class); 223 } 224 params.add(String .class); 225 Class [] paramClasses = (Class [])params.toArray(new Class [params.size()]); 226 try { 227 c.getMethod(getPreMethodName(), paramClasses); 228 owner = c.getName(); 229 break; 230 } catch (Exception e) { 231 } 232 } 233 if (owner == null) { 234 throw new ClassGenerationException( 235 null, 236 icg.args.toString(), 237 "Cannot find a controller class providing a '" + 238 getPreMethodName() + "' method with the good arguments"); 239 } 240 owner = owner.replace('.', '/'); 241 242 int hashcode = getControllerInterfaceName().hashCode(); 243 delegateFieldName = "d" + Integer.toHexString(hashcode); 244 delegateFieldDesc = "L" + owner + ";"; 245 246 icg.cw.visitField( 247 ACC_PRIVATE, delegateFieldName, delegateFieldDesc, null, null); 248 249 cv.visitVarInsn(ALOAD, 0); 250 cv.visitVarInsn(ALOAD, 1); 251 cv.visitLdcInsn(getControllerInterfaceName()); 252 cv.visitMethodInsn( 253 INVOKEVIRTUAL, 254 Type.getInternalName(InitializationContext.class), 255 "getInterface", 256 "(" + Type.getDescriptor(String .class) + ")" + 257 Type.getDescriptor(Object .class)); 258 cv.visitTypeInsn(CHECKCAST, owner); 259 cv.visitFieldInsn(PUTFIELD, icg.name, delegateFieldName, delegateFieldDesc); 260 } 261 262 protected int getInterceptionCodeFormals (final Method m) { 263 return AbstractClassGenerator.getSize(getContextType()); 265 } 266 267 public void generateCloneCode (final CodeVisitor cv) { 268 cv.visitVarInsn(ALOAD, 1); 269 cv.visitVarInsn(ALOAD, 0); 270 cv.visitFieldInsn(GETFIELD, icg.name, delegateFieldName, delegateFieldDesc); 271 cv.visitFieldInsn(PUTFIELD, icg.name, delegateFieldName, delegateFieldDesc); 272 } 273 274 278 protected void generateInterceptionCodeBlock ( 279 final Method m, 280 final boolean pre, 281 final CodeVisitor cv, 282 final int formals) 283 { 284 Class c = getContextType(); 285 String desc = Type.getDescriptor(c); 286 287 cv.visitVarInsn(ALOAD, 0); 293 if (delegateFieldName != null) { 298 cv.visitFieldInsn( 299 GETFIELD, icg.name, delegateFieldName, delegateFieldDesc); 300 } 301 302 if (needsInterfaceName()) { 303 String name = getInterfaceName(m); 304 if (name == null) { 305 cv.visitInsn(ACONST_NULL); 306 } else { 307 cv.visitLdcInsn(name); 308 } 309 } 310 311 if (needsTargetObject()) { 312 cv.visitVarInsn(ALOAD, 0); 314 cv.visitFieldInsn( 315 GETFIELD, icg.name, icg.implFieldName, icg.implFieldDesc); 316 } 317 318 cv.visitLdcInsn(getMethodName(m)); 320 321 if (!pre && c != Void.TYPE) { 325 cv.visitVarInsn( 326 ILOAD + AbstractClassGenerator.getOpcodeOffset(c), formals); 327 } 328 329 331 if (owner == null) { 333 if (delegateFieldDesc == null) { 334 owner = icg.name; 335 } else { 336 owner = delegateFieldDesc.substring(1, delegateFieldDesc.length() - 1); 337 } 338 } 339 340 String name = pre ? getPreMethodName() : getPostMethodName(); 342 343 if (pre) { 345 desc = "Ljava/lang/String;)" + desc; 346 } else if (c != Void.TYPE) { 347 desc = "Ljava/lang/String;" + desc + ")V"; 348 } else { 349 desc = "Ljava/lang/String;)V"; 350 } 351 if (needsTargetObject()) { 352 desc = "Ljava/lang/Object;" + desc; 353 } 354 if (needsInterfaceName()) { 355 desc = "Ljava/lang/String;" + desc; 356 } 357 358 cv.visitMethodInsn(INVOKEVIRTUAL, owner, name, "(" + desc); 360 361 if (pre && c != Void.TYPE) { 365 cv.visitVarInsn( 366 ISTORE + AbstractClassGenerator.getOpcodeOffset(c), formals); 367 } 368 } 369 370 374 381 382 protected abstract String getControllerInterfaceName (); 383 384 391 392 protected abstract String getPreMethodName (); 393 394 401 402 protected abstract String getPostMethodName (); 403 404 411 412 protected abstract Class getContextType (); 413 414 422 423 protected abstract String getMethodName (Method m); 424 425 434 435 protected boolean needsInterfaceName () { 436 return false; 437 } 438 439 447 448 private String getInterfaceName (Method m) { 449 if (args != null) { 450 String desc = m.getName()+Type.getMethodDescriptor(m); 451 List itfs = icg.interfaces; 452 for (int i = 0; i < itfs.size(); ++i) { 453 String itf = ((String )itfs.get(i)).replace('/', '.'); 454 Class c; 455 try { 456 c = icg.loader.loadClass(itf, icg.classLoader); 457 } catch (ClassNotFoundException e) { 458 continue; 459 } 460 Method [] meths = c.getMethods(); 461 for (int j = 0; j < meths.length; ++j) { 462 Method meth = meths[j]; 463 if (desc.equals(meth.getName()+Type.getMethodDescriptor(meth))) { 464 return args.getSubTree(i).toString(); 465 } 466 } 467 } 468 } 469 return null; 470 } 471 472 480 481 protected boolean needsTargetObject () { 482 return false; 483 } 484 } 485 | Popular Tags |