1 28 package org.jruby.runtime.callback; 29 30 import java.io.File ; 31 import java.io.FileOutputStream ; 32 33 import org.jruby.Ruby; 34 import org.jruby.RubyKernel; 35 import org.objectweb.asm.ClassWriter; 36 import org.objectweb.asm.MethodVisitor; 37 import org.objectweb.asm.Opcodes; 38 import org.jruby.runtime.Arity; 39 import org.jruby.runtime.Block; 40 import org.jruby.runtime.CallbackFactory; 41 import org.jruby.runtime.CompiledBlockCallback; 42 import org.jruby.runtime.ThreadContext; 43 import org.jruby.runtime.builtin.IRubyObject; 44 import org.jruby.util.CodegenUtils; 45 46 public class DumpingInvocationCallbackFactory extends CallbackFactory implements Opcodes { 47 private final static CodegenUtils cg = CodegenUtils.instance; 48 49 private final Class type; 50 private final String typePath; 51 private final Ruby runtime; 52 53 private final static String SUPER_CLASS = cg.p(InvocationCallback.class); 54 private final static String FAST_SUPER_CLASS = cg.p(FastInvocationCallback.class); 55 private final static String BLOCK_ID = cg.ci(Block.class); 56 private final static String CALL_SIG = cg.sig(RubyKernel.IRUBY_OBJECT, cg.params(Object .class, Object [].class, Block.class)); 57 private final static String FAST_CALL_SIG = cg.sig(RubyKernel.IRUBY_OBJECT, cg.params(Object .class, Object [].class)); 58 private final static String BLOCK_CALL_SIG = cg.sig(RubyKernel.IRUBY_OBJECT, cg.params(ThreadContext.class, RubyKernel.IRUBY_OBJECT, IRubyObject[].class, Block.class, IRubyObject[][].class)); 59 private final static String IRUB = cg.p(RubyKernel.IRUBY_OBJECT); 60 private final static String IRUB_ID = cg.ci(RubyKernel.IRUBY_OBJECT); 61 62 private String dumpPath; 63 64 public DumpingInvocationCallbackFactory(Ruby runtime, Class type, String path) { 65 this.type = type; 66 this.typePath = cg.p(type); 67 this.runtime = runtime; 68 this.dumpPath = path; 69 } 70 71 private String getReturnName(String method, Class [] args) throws Exception { 72 String t = type.getMethod(method,args).getReturnType().getName().replace('.','/'); 73 if("void".equalsIgnoreCase(t)) { 74 throw new IllegalArgumentException ("Method " + method + " has a void return type. This is not allowed in JRuby."); 75 } 76 return t; 77 } 78 79 private ClassWriter createCtor(String namePath) throws Exception { 80 ClassWriter cw = new ClassWriter(true); 81 cw.visit(V1_4, ACC_PUBLIC + ACC_SUPER, namePath, null, SUPER_CLASS, null); 82 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); 83 mv.visitCode(); 84 mv.visitVarInsn(ALOAD, 0); 85 mv.visitMethodInsn(INVOKESPECIAL, SUPER_CLASS, "<init>", "()V"); 86 mv.visitInsn(RETURN); 87 mv.visitMaxs(1, 1); 88 mv.visitEnd(); 89 return cw; 90 } 91 92 private ClassWriter createCtorFast(String namePath) throws Exception { 93 ClassWriter cw = new ClassWriter(true); 94 cw.visit(V1_4, ACC_PUBLIC + ACC_SUPER, namePath, null, FAST_SUPER_CLASS, null); 95 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); 96 mv.visitCode(); 97 mv.visitVarInsn(ALOAD, 0); 98 mv.visitMethodInsn(INVOKESPECIAL, FAST_SUPER_CLASS, "<init>", "()V"); 99 mv.visitInsn(RETURN); 100 mv.visitMaxs(1, 1); 101 mv.visitEnd(); 102 return cw; 103 } 104 105 private ClassWriter createBlockCtor(String namePath) throws Exception { 106 ClassWriter cw = new ClassWriter(true); 107 cw.visit(V1_4, ACC_PUBLIC + ACC_SUPER, namePath, null, cg.p(Object .class), new String [] { cg.p(CompiledBlockCallback.class) }); 108 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); 109 mv.visitCode(); 110 mv.visitVarInsn(ALOAD, 0); 111 mv.visitMethodInsn(INVOKESPECIAL, cg.p(Object .class), "<init>", "()V"); 112 mv.visitInsn(RETURN); 113 mv.visitMaxs(1, 1); 114 mv.visitEnd(); 115 return cw; 116 } 117 118 private Class tryClass(String name) { 119 try { 120 return Class.forName(name,true,runtime.getJRubyClassLoader()); 121 } catch(Exception e) { 122 return null; 123 } 124 } 125 126 private MethodVisitor startCall(ClassWriter cw) { 127 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "call", CALL_SIG, null, null);; 128 mv.visitCode(); 129 mv.visitVarInsn(ALOAD, 1); 130 mv.visitTypeInsn(CHECKCAST, typePath); 131 return mv; 132 } 133 134 private MethodVisitor startCallS(ClassWriter cw) { 135 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "call", CALL_SIG, null, null);; 136 mv.visitCode(); 137 mv.visitVarInsn(ALOAD, 1); 138 mv.visitTypeInsn(CHECKCAST, IRUB); 139 return mv; 140 } 141 142 private MethodVisitor startCallFast(ClassWriter cw) { 143 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "call", FAST_CALL_SIG, null, null);; 144 mv.visitCode(); 145 mv.visitVarInsn(ALOAD, 1); 146 mv.visitTypeInsn(CHECKCAST, typePath); 147 return mv; 148 } 149 150 private MethodVisitor startCallSFast(ClassWriter cw) { 151 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "call", FAST_CALL_SIG, null, null);; 152 mv.visitCode(); 153 mv.visitVarInsn(ALOAD, 1); 154 mv.visitTypeInsn(CHECKCAST, IRUB); 155 return mv; 156 } 157 158 private MethodVisitor startBlockCall(ClassWriter cw) { 159 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "call", BLOCK_CALL_SIG, null, null);; 160 mv.visitCode(); 161 return mv; 162 } 163 164 private Class endCall(ClassWriter cw, MethodVisitor mv, String name) { 165 mv.visitEnd(); 166 cw.visitEnd(); 167 byte[] code = cw.toByteArray(); 168 String cname = name.replace('.','/'); 169 File f = new File (dumpPath,cname+".class"); 170 f.getParentFile().mkdirs(); 171 try { 172 FileOutputStream fos = new FileOutputStream (f); 173 fos.write(code); 174 fos.close(); 175 } catch(Exception e) { 176 } 177 return runtime.getJRubyClassLoader().defineClass(name, code); 178 } 179 180 public Callback getMethod(String method) { 181 String mname = type.getName() + "Invoker" + method + "0"; 182 String mnamePath = typePath + "Invoker" + method + "0"; 183 Class c = tryClass(mname); 184 try { 185 if(c == null) { 186 String ret = getReturnName(method, new Class []{Block.class}); 187 ClassWriter cw = createCtor(mnamePath); 188 MethodVisitor mv = startCall(cw); 189 mv.visitVarInsn(ALOAD, 3); 190 mv.visitMethodInsn(INVOKEVIRTUAL, typePath, method, "(" + BLOCK_ID + ")L" + ret + ";"); 191 mv.visitInsn(ARETURN); 192 mv.visitMaxs(1, 3); 193 c = endCall(cw,mv,mname); 194 } 195 InvocationCallback ic = (InvocationCallback)c.newInstance(); 196 ic.setArity(Arity.noArguments()); 197 return ic; 198 } catch(IllegalArgumentException e) { 199 throw e; 200 } catch(Exception e) { 201 throw new IllegalArgumentException (e.getMessage()); 202 } 203 } 204 205 public Callback getMethod(String method, Class arg1) { 206 String mname = type.getName() + "Invoker" + method + "1"; 207 String mnamePath = typePath + "Invoker" + method + "1"; 208 Class c = tryClass(mname); 209 try { 210 if(c == null) { 211 String ret = getReturnName(method,new Class []{arg1,Block.class}); 212 ClassWriter cw = createCtor(mnamePath); 213 MethodVisitor mv = startCall(cw); 214 mv.visitVarInsn(ALOAD, 2); 215 mv.visitInsn(ICONST_0); 216 mv.visitInsn(AALOAD); 217 mv.visitTypeInsn(CHECKCAST, cg.p(arg1)); 218 mv.visitVarInsn(ALOAD, 3); 219 mv.visitMethodInsn(INVOKEVIRTUAL, typePath, method, "("+cg.ci(arg1)+BLOCK_ID+")L"+ret+";"); 220 mv.visitInsn(ARETURN); 221 mv.visitMaxs(3, 3); 222 c = endCall(cw,mv,mname); 223 } 224 InvocationCallback ic = (InvocationCallback)c.newInstance(); 225 ic.setArity(Arity.singleArgument()); 226 return ic; 227 } catch(IllegalArgumentException e) { 228 throw e; 229 } catch(Exception e) { 230 throw new IllegalArgumentException (e.getMessage()); 231 } 232 } 233 234 public Callback getMethod(String method, Class arg1, Class arg2) { 235 String mname = type.getName() + "Invoker" + method + "2"; 236 String mnamePath = typePath + "Invoker" + method + "2"; 237 Class c = tryClass(mname); 238 try { 239 if(c == null) { 240 String ret = getReturnName(method,new Class []{arg1,arg2,Block.class}); 241 ClassWriter cw = createCtor(mnamePath); 242 MethodVisitor mv = startCall(cw); 243 mv.visitVarInsn(ALOAD, 2); 244 mv.visitInsn(ICONST_0); 245 mv.visitInsn(AALOAD); 246 mv.visitTypeInsn(CHECKCAST, cg.p(arg1)); 247 mv.visitVarInsn(ALOAD, 2); 248 mv.visitInsn(ICONST_1); 249 mv.visitInsn(AALOAD); 250 mv.visitTypeInsn(CHECKCAST, cg.p(arg2)); 251 mv.visitVarInsn(ALOAD, 3); 252 mv.visitMethodInsn(INVOKEVIRTUAL, typePath, method, "("+cg.ci(arg1)+cg.ci(arg2)+BLOCK_ID+")L"+ret+";"); 253 mv.visitInsn(ARETURN); 254 mv.visitMaxs(4, 3); 255 c = endCall(cw,mv,mname); 256 } 257 InvocationCallback ic = (InvocationCallback)c.newInstance(); 258 ic.setArity(Arity.twoArguments()); 259 return ic; 260 } catch(IllegalArgumentException e) { 261 throw e; 262 } catch(Exception e) { 263 throw new IllegalArgumentException (e.getMessage()); 264 } 265 } 266 267 public Callback getMethod(String method, Class arg1, Class arg2, Class arg3) { 268 String mname = type.getName() + "Invoker" + method + "3"; 269 String mnamePath = typePath + "Invoker" + method + "3"; 270 Class c = tryClass(mname); 271 try { 272 if(c == null) { 273 String ret = getReturnName(method,new Class []{arg1,arg2,arg3,Block.class}); 274 ClassWriter cw = createCtor(mnamePath); 275 MethodVisitor mv = startCall(cw); 276 mv.visitVarInsn(ALOAD, 2); 277 mv.visitInsn(ICONST_0); 278 mv.visitInsn(AALOAD); 279 mv.visitTypeInsn(CHECKCAST, cg.p(arg1)); 280 mv.visitVarInsn(ALOAD, 2); 281 mv.visitInsn(ICONST_1); 282 mv.visitInsn(AALOAD); 283 mv.visitTypeInsn(CHECKCAST, cg.p(arg2)); 284 mv.visitVarInsn(ALOAD, 2); 285 mv.visitInsn(ICONST_2); 286 mv.visitInsn(AALOAD); 287 mv.visitTypeInsn(CHECKCAST, cg.p(arg3)); 288 mv.visitVarInsn(ALOAD, 3); 289 mv.visitMethodInsn(INVOKEVIRTUAL, typePath, method, "("+cg.ci(arg1)+cg.ci(arg2)+cg.ci(arg3)+BLOCK_ID+")L"+ret+";"); 290 mv.visitInsn(ARETURN); 291 mv.visitMaxs(5, 3); 292 c = endCall(cw,mv,mname); 293 } 294 InvocationCallback ic = (InvocationCallback)c.newInstance(); 295 ic.setArity(Arity.fixed(3)); 296 return ic; 297 } catch(IllegalArgumentException e) { 298 throw e; 299 } catch(Exception e) { 300 throw new IllegalArgumentException (e.getMessage()); 301 } 302 } 303 304 public Callback getSingletonMethod(String method) { 305 String mname = type.getName() + "InvokerS" + method + "0"; 306 String mnamePath = typePath + "InvokerS" + method + "0"; 307 Class c = tryClass(mname); 308 try { 309 if(c == null) { 310 String ret = getReturnName(method,new Class []{RubyKernel.IRUBY_OBJECT,Block.class}); 311 ClassWriter cw = createCtor(mnamePath); 312 MethodVisitor mv = startCallS(cw); 313 mv.visitVarInsn(ALOAD, 3); 314 mv.visitMethodInsn(INVOKESTATIC, typePath, method, "(" + IRUB_ID + BLOCK_ID + ")L" + ret +";"); 315 mv.visitInsn(ARETURN); 316 mv.visitMaxs(1, 3); 317 c = endCall(cw,mv,mname); 318 } 319 InvocationCallback ic = (InvocationCallback)c.newInstance(); 320 ic.setArity(Arity.noArguments()); 321 return ic; 322 } catch(IllegalArgumentException e) { 323 throw e; 324 } catch(Exception e) { 325 throw new IllegalArgumentException (e.getMessage()); 326 } 327 } 328 329 public Callback getSingletonMethod(String method, Class arg1) { 330 String mname = type.getName() + "InvokerS" + method + "1"; 331 String mnamePath = typePath + "InvokerS" + method + "1"; 332 Class c = tryClass(mname); 333 try { 334 if(c == null) { 335 String ret = getReturnName(method,new Class []{RubyKernel.IRUBY_OBJECT,arg1,Block.class}); 336 ClassWriter cw = createCtor(mnamePath); 337 MethodVisitor mv = startCallS(cw); 338 mv.visitVarInsn(ALOAD, 2); 339 mv.visitInsn(ICONST_0); 340 mv.visitInsn(AALOAD); 341 mv.visitTypeInsn(CHECKCAST, cg.p(arg1)); 342 mv.visitVarInsn(ALOAD, 3); 343 mv.visitMethodInsn(INVOKESTATIC, typePath, method, "(" + IRUB_ID + cg.ci(arg1) + BLOCK_ID + ")L" + ret + ";"); 344 mv.visitInsn(ARETURN); 345 mv.visitMaxs(3, 3); 346 c = endCall(cw,mv,mname); 347 } 348 InvocationCallback ic = (InvocationCallback)c.newInstance(); 349 ic.setArity(Arity.singleArgument()); 350 return ic; 351 } catch(IllegalArgumentException e) { 352 throw e; 353 } catch(Exception e) { 354 throw new IllegalArgumentException (e.getMessage()); 355 } 356 } 357 358 public Callback getSingletonMethod(String method, Class arg1, Class arg2) { 359 String mname = type.getName() + "InvokerS" + method + "2"; 360 String mnamePath = typePath + "InvokerS" + method + "2"; 361 Class c = tryClass(mname); 362 try { 363 if(c == null) { 364 String ret = getReturnName(method,new Class []{RubyKernel.IRUBY_OBJECT,arg1,arg2,Block.class}); 365 ClassWriter cw = createCtor(mnamePath); 366 MethodVisitor mv = startCallS(cw); 367 mv.visitVarInsn(ALOAD, 2); 368 mv.visitInsn(ICONST_0); 369 mv.visitInsn(AALOAD); 370 mv.visitTypeInsn(CHECKCAST, cg.p(arg1)); 371 mv.visitVarInsn(ALOAD, 2); 372 mv.visitInsn(ICONST_1); 373 mv.visitInsn(AALOAD); 374 mv.visitTypeInsn(CHECKCAST, cg.p(arg2)); 375 mv.visitVarInsn(ALOAD, 3); 376 mv.visitMethodInsn(INVOKESTATIC, typePath, method, "(" + IRUB_ID + cg.ci(arg1) + cg.ci(arg2) + BLOCK_ID + ")L" + ret + ";"); 377 mv.visitInsn(ARETURN); 378 mv.visitMaxs(4, 4); 379 c = endCall(cw,mv,mname); 380 } 381 InvocationCallback ic = (InvocationCallback)c.newInstance(); 382 ic.setArity(Arity.twoArguments()); 383 return ic; 384 } catch(IllegalArgumentException e) { 385 throw e; 386 } catch(Exception e) { 387 throw new IllegalArgumentException (e.getMessage()); 388 } 389 } 390 391 public Callback getSingletonMethod(String method, Class arg1, Class arg2, Class arg3) { 392 String mname = type.getName() + "InvokerS" + method + "3"; 393 String mnamePath = typePath + "InvokerS" + method + "3"; 394 Class c = tryClass(mname); 395 try { 396 if(c == null) { 397 String ret = getReturnName(method,new Class []{RubyKernel.IRUBY_OBJECT,arg1,arg2,arg3,Block.class}); 398 ClassWriter cw = createCtor(mnamePath); 399 MethodVisitor mv = startCallS(cw); 400 mv.visitVarInsn(ALOAD, 2); 401 mv.visitInsn(ICONST_0); 402 mv.visitInsn(AALOAD); 403 mv.visitTypeInsn(CHECKCAST, cg.p(arg1)); 404 mv.visitVarInsn(ALOAD, 2); 405 mv.visitInsn(ICONST_1); 406 mv.visitInsn(AALOAD); 407 mv.visitTypeInsn(CHECKCAST, cg.p(arg2)); 408 mv.visitVarInsn(ALOAD, 2); 409 mv.visitInsn(ICONST_2); 410 mv.visitInsn(AALOAD); 411 mv.visitTypeInsn(CHECKCAST, cg.p(arg3)); 412 mv.visitVarInsn(ALOAD, 3); 413 mv.visitMethodInsn(INVOKESTATIC, typePath, method, "(" + IRUB_ID + cg.ci(arg1) + cg.ci(arg2) + cg.ci(arg3) + BLOCK_ID + ")L" + ret + ";"); 414 mv.visitInsn(ARETURN); 415 mv.visitMaxs(5, 3); 416 c = endCall(cw,mv,mname); 417 } 418 InvocationCallback ic = (InvocationCallback)c.newInstance(); 419 ic.setArity(Arity.fixed(3)); 420 return ic; 421 } catch(IllegalArgumentException e) { 422 throw e; 423 } catch(Exception e) { 424 throw new IllegalArgumentException (e.getMessage()); 425 } 426 } 427 428 public Callback getBlockMethod(String method) { 429 return new ReflectionCallback( 431 type, 432 method, 433 new Class [] { RubyKernel.IRUBY_OBJECT, RubyKernel.IRUBY_OBJECT }, 434 false, 435 true, 436 Arity.fixed(2), false); 437 } 438 439 public CompiledBlockCallback getBlockCallback(String method) { 440 String mname = type.getName() + "Block" + method + "xx1"; 441 String mnamePath = typePath + "Block" + method + "xx1"; 442 Class c = tryClass(mname); 443 try { 444 if(c == null) { 445 ClassWriter cw = createBlockCtor(mnamePath); 446 MethodVisitor mv = startBlockCall(cw); 447 mv.visitVarInsn(ALOAD, 1); 448 mv.visitVarInsn(ALOAD, 2); 449 mv.visitVarInsn(ALOAD, 3); 450 mv.visitVarInsn(ALOAD, 4); 451 mv.visitVarInsn(ALOAD, 5); 452 mv.visitMethodInsn(INVOKESTATIC, typePath, method, 453 cg.sig(RubyKernel.IRUBY_OBJECT, cg.params(ThreadContext.class, RubyKernel.IRUBY_OBJECT, IRubyObject[].class, Block.class, IRubyObject[][].class))); 454 mv.visitInsn(ARETURN); 455 mv.visitMaxs(2, 3); 456 c = endCall(cw,mv,mname); 457 } 458 CompiledBlockCallback ic = (CompiledBlockCallback)c.newInstance(); 459 return ic; 460 } catch(IllegalArgumentException e) { 461 throw e; 462 } catch(Exception e) { 463 throw new IllegalArgumentException (e.getMessage()); 464 } 465 } 466 467 public Callback getOptSingletonMethod(String method) { 468 String mname = type.getName() + "InvokerS" + method + "xx1"; 469 String mnamePath = typePath + "InvokerS" + method + "xx1"; 470 Class c = tryClass(mname); 471 try { 472 if(c == null) { 473 String ret = getReturnName(method,new Class []{RubyKernel.IRUBY_OBJECT,IRubyObject[].class,Block.class}); 474 ClassWriter cw = createCtor(mnamePath); 475 MethodVisitor mv = startCallS(cw); 476 mv.visitVarInsn(ALOAD, 2); 477 mv.visitTypeInsn(CHECKCAST, "[" + IRUB_ID); 478 mv.visitTypeInsn(CHECKCAST, "[" + IRUB_ID); 479 mv.visitVarInsn(ALOAD, 3); 480 mv.visitMethodInsn(INVOKESTATIC, typePath, method, "(" + IRUB_ID + "[" + IRUB_ID + BLOCK_ID + ")L"+ret+";"); 481 mv.visitInsn(ARETURN); 482 mv.visitMaxs(2, 3); 483 c = endCall(cw,mv,mname); 484 } 485 InvocationCallback ic = (InvocationCallback)c.newInstance(); 486 ic.setArity(Arity.optional()); 487 return ic; 488 } catch(IllegalArgumentException e) { 489 throw e; 490 } catch(Exception e) { 491 throw new IllegalArgumentException (e.getMessage()); 492 } 493 } 494 495 public Callback getOptMethod(String method) { 496 String mname = type.getName() + "Invoker" + method + "xx1"; 497 String mnamePath = typePath + "Invoker" + method + "xx1"; 498 Class c = tryClass(mname); 499 try { 500 if(c == null) { 501 String ret = getReturnName(method,new Class []{IRubyObject[].class, Block.class}); 502 ClassWriter cw = createCtor(mnamePath); 503 MethodVisitor mv = startCall(cw); 504 mv.visitVarInsn(ALOAD, 2); 505 mv.visitTypeInsn(CHECKCAST, "[" + IRUB_ID); 506 mv.visitTypeInsn(CHECKCAST, "[" + IRUB_ID); 507 mv.visitVarInsn(ALOAD, 3); 508 mv.visitMethodInsn(INVOKEVIRTUAL, typePath, method, "([" + IRUB_ID + BLOCK_ID + ")L" + ret + ";"); 509 mv.visitInsn(ARETURN); 510 mv.visitMaxs(2, 3); 511 c = endCall(cw,mv,mname); 512 } 513 InvocationCallback ic = (InvocationCallback)c.newInstance(); 514 ic.setArity(Arity.optional()); 515 return ic; 516 } catch(IllegalArgumentException e) { 517 throw e; 518 } catch(Exception e) { 519 throw new IllegalArgumentException (e.getMessage()); 520 } 521 } 522 523 public Callback getFastMethod(String method) { 524 String mname = type.getName() + "Invoker" + method + "0"; 525 String mnamePath = typePath + "Invoker" + method + "0"; 526 Class c = tryClass(mname); 527 try { 528 if(c == null) { 529 String ret = getReturnName(method, null); 530 ClassWriter cw = createCtorFast(mnamePath); 531 MethodVisitor mv = startCallFast(cw); 532 mv.visitMethodInsn(INVOKEVIRTUAL, typePath, method, "()L" + ret + ";"); 533 mv.visitInsn(ARETURN); 534 mv.visitMaxs(1, 3); 535 c = endCall(cw,mv,mname); 536 } 537 FastInvocationCallback ic = (FastInvocationCallback)c.newInstance(); 538 ic.setArity(Arity.noArguments()); 539 return ic; 540 } catch(IllegalArgumentException e) { 541 throw e; 542 } catch(Exception e) { 543 throw new IllegalArgumentException (e.getMessage()); 544 } 545 } 546 547 public Callback getFastMethod(String method, Class arg1) { 548 String mname = type.getName() + "Invoker" + method + "1"; 549 String mnamePath = typePath + "Invoker" + method + "1"; 550 Class c = tryClass(mname); 551 try { 552 if(c == null) { 553 String ret = getReturnName(method,new Class []{arg1}); 554 ClassWriter cw = createCtorFast(mnamePath); 555 MethodVisitor mv = startCallFast(cw); 556 mv.visitVarInsn(ALOAD, 2); 557 mv.visitInsn(ICONST_0); 558 mv.visitInsn(AALOAD); 559 mv.visitTypeInsn(CHECKCAST, cg.p(arg1)); 560 mv.visitMethodInsn(INVOKEVIRTUAL, typePath, method, "("+cg.ci(arg1)+")L"+ret+";"); 561 mv.visitInsn(ARETURN); 562 mv.visitMaxs(3, 3); 563 c = endCall(cw,mv,mname); 564 } 565 FastInvocationCallback ic = (FastInvocationCallback)c.newInstance(); 566 ic.setArity(Arity.singleArgument()); 567 return ic; 568 } catch(IllegalArgumentException e) { 569 throw e; 570 } catch(Exception e) { 571 throw new IllegalArgumentException (e.getMessage()); 572 } 573 } 574 575 public Callback getFastMethod(String method, Class arg1, Class arg2) { 576 String mname = type.getName() + "Invoker" + method + "2"; 577 String mnamePath = typePath + "Invoker" + method + "2"; 578 Class c = tryClass(mname); 579 try { 580 if(c == null) { 581 String ret = getReturnName(method,new Class []{arg1,arg2}); 582 ClassWriter cw = createCtorFast(mnamePath); 583 MethodVisitor mv = startCallFast(cw); 584 mv.visitVarInsn(ALOAD, 2); 585 mv.visitInsn(ICONST_0); 586 mv.visitInsn(AALOAD); 587 mv.visitTypeInsn(CHECKCAST, cg.p(arg1)); 588 mv.visitVarInsn(ALOAD, 2); 589 mv.visitInsn(ICONST_1); 590 mv.visitInsn(AALOAD); 591 mv.visitTypeInsn(CHECKCAST, cg.p(arg2)); 592 mv.visitMethodInsn(INVOKEVIRTUAL, typePath, method, "("+cg.ci(arg1)+cg.ci(arg2)+")L"+ret+";"); 593 mv.visitInsn(ARETURN); 594 mv.visitMaxs(4, 3); 595 c = endCall(cw,mv,mname); 596 } 597 FastInvocationCallback ic = (FastInvocationCallback)c.newInstance(); 598 ic.setArity(Arity.twoArguments()); 599 return ic; 600 } catch(IllegalArgumentException e) { 601 throw e; 602 } catch(Exception e) { 603 throw new IllegalArgumentException (e.getMessage()); 604 } 605 } 606 607 public Callback getFastMethod(String method, Class arg1, Class arg2, Class arg3) { 608 String mname = type.getName() + "Invoker" + method + "3"; 609 String mnamePath = typePath + "Invoker" + method + "3"; 610 Class c = tryClass(mname); 611 try { 612 if(c == null) { 613 String ret = getReturnName(method,new Class []{arg1,arg2,arg3}); 614 ClassWriter cw = createCtorFast(mnamePath); 615 MethodVisitor mv = startCallFast(cw); 616 mv.visitVarInsn(ALOAD, 2); 617 mv.visitInsn(ICONST_0); 618 mv.visitInsn(AALOAD); 619 mv.visitTypeInsn(CHECKCAST, cg.p(arg1)); 620 mv.visitVarInsn(ALOAD, 2); 621 mv.visitInsn(ICONST_1); 622 mv.visitInsn(AALOAD); 623 mv.visitTypeInsn(CHECKCAST, cg.p(arg2)); 624 mv.visitVarInsn(ALOAD, 2); 625 mv.visitInsn(ICONST_2); 626 mv.visitInsn(AALOAD); 627 mv.visitTypeInsn(CHECKCAST, cg.p(arg3)); 628 mv.visitMethodInsn(INVOKEVIRTUAL, typePath, method, "("+cg.ci(arg1)+cg.ci(arg2)+cg.ci(arg3)+")L"+ret+";"); 629 mv.visitInsn(ARETURN); 630 mv.visitMaxs(5, 3); 631 c = endCall(cw,mv,mname); 632 } 633 FastInvocationCallback ic = (FastInvocationCallback)c.newInstance(); 634 ic.setArity(Arity.fixed(3)); 635 return ic; 636 } catch(IllegalArgumentException e) { 637 throw e; 638 } catch(Exception e) { 639 throw new IllegalArgumentException (e.getMessage()); 640 } 641 } 642 643 public Callback getFastSingletonMethod(String method) { 644 String mname = type.getName() + "InvokerS" + method + "0"; 645 String mnamePath = typePath + "InvokerS" + method + "0"; 646 Class c = tryClass(mname); 647 try { 648 if(c == null) { 649 String ret = getReturnName(method,new Class []{RubyKernel.IRUBY_OBJECT}); 650 ClassWriter cw = createCtorFast(mnamePath); 651 MethodVisitor mv = startCallSFast(cw); 652 mv.visitMethodInsn(INVOKESTATIC, typePath, method, "(" + IRUB_ID + ")L" + ret +";"); 653 mv.visitInsn(ARETURN); 654 mv.visitMaxs(1, 3); 655 c = endCall(cw,mv,mname); 656 } 657 FastInvocationCallback ic = (FastInvocationCallback)c.newInstance(); 658 ic.setArity(Arity.noArguments()); 659 return ic; 660 } catch(IllegalArgumentException e) { 661 throw e; 662 } catch(Exception e) { 663 throw new IllegalArgumentException (e.getMessage()); 664 } 665 } 666 667 public Callback getFastSingletonMethod(String method, Class arg1) { 668 String mname = type.getName() + "InvokerS" + method + "1"; 669 String mnamePath = typePath + "InvokerS" + method + "1"; 670 Class c = tryClass(mname); 671 try { 672 if(c == null) { 673 String ret = getReturnName(method,new Class []{RubyKernel.IRUBY_OBJECT,arg1}); 674 ClassWriter cw = createCtorFast(mnamePath); 675 MethodVisitor mv = startCallSFast(cw); 676 mv.visitVarInsn(ALOAD, 2); 677 mv.visitInsn(ICONST_0); 678 mv.visitInsn(AALOAD); 679 mv.visitTypeInsn(CHECKCAST, cg.p(arg1)); 680 mv.visitMethodInsn(INVOKESTATIC, typePath, method, "(" + IRUB_ID + cg.ci(arg1) + ")L" + ret + ";"); 681 mv.visitInsn(ARETURN); 682 mv.visitMaxs(3, 3); 683 c = endCall(cw,mv,mname); 684 } 685 FastInvocationCallback ic = (FastInvocationCallback)c.newInstance(); 686 ic.setArity(Arity.singleArgument()); 687 return ic; 688 } catch(IllegalArgumentException e) { 689 throw e; 690 } catch(Exception e) { 691 throw new IllegalArgumentException (e.getMessage()); 692 } 693 } 694 695 public Callback getFastSingletonMethod(String method, Class arg1, Class arg2) { 696 String mname = type.getName() + "InvokerS" + method + "2"; 697 String mnamePath = typePath + "InvokerS" + method + "2"; 698 Class c = tryClass(mname); 699 try { 700 if(c == null) { 701 String ret = getReturnName(method,new Class []{RubyKernel.IRUBY_OBJECT,arg1,arg2}); 702 ClassWriter cw = createCtorFast(mnamePath); 703 MethodVisitor mv = startCallSFast(cw); 704 mv.visitVarInsn(ALOAD, 2); 705 mv.visitInsn(ICONST_0); 706 mv.visitInsn(AALOAD); 707 mv.visitTypeInsn(CHECKCAST, cg.p(arg1)); 708 mv.visitVarInsn(ALOAD, 2); 709 mv.visitInsn(ICONST_1); 710 mv.visitInsn(AALOAD); 711 mv.visitTypeInsn(CHECKCAST, cg.p(arg2)); 712 mv.visitMethodInsn(INVOKESTATIC, typePath, method, "(" + IRUB_ID + cg.ci(arg1) + cg.ci(arg2) + ")L" + ret + ";"); 713 mv.visitInsn(ARETURN); 714 mv.visitMaxs(4, 4); 715 c = endCall(cw,mv,mname); 716 } 717 FastInvocationCallback ic = (FastInvocationCallback)c.newInstance(); 718 ic.setArity(Arity.twoArguments()); 719 return ic; 720 } catch(IllegalArgumentException e) { 721 throw e; 722 } catch(Exception e) { 723 throw new IllegalArgumentException (e.getMessage()); 724 } 725 } 726 727 public Callback getFastSingletonMethod(String method, Class arg1, Class arg2, Class arg3) { 728 String mname = type.getName() + "InvokerS" + method + "3"; 729 String mnamePath = typePath + "InvokerS" + method + "3"; 730 Class c = tryClass(mname); 731 try { 732 if(c == null) { 733 String ret = getReturnName(method,new Class []{RubyKernel.IRUBY_OBJECT,arg1,arg2,arg3}); 734 ClassWriter cw = createCtorFast(mnamePath); 735 MethodVisitor mv = startCallSFast(cw); 736 mv.visitVarInsn(ALOAD, 2); 737 mv.visitInsn(ICONST_0); 738 mv.visitInsn(AALOAD); 739 mv.visitTypeInsn(CHECKCAST, cg.p(arg1)); 740 mv.visitVarInsn(ALOAD, 2); 741 mv.visitInsn(ICONST_1); 742 mv.visitInsn(AALOAD); 743 mv.visitTypeInsn(CHECKCAST, cg.p(arg2)); 744 mv.visitVarInsn(ALOAD, 2); 745 mv.visitInsn(ICONST_2); 746 mv.visitInsn(AALOAD); 747 mv.visitTypeInsn(CHECKCAST, cg.p(arg3)); 748 mv.visitMethodInsn(INVOKESTATIC, typePath, method, "(" + IRUB_ID + cg.ci(arg1) + cg.ci(arg2) + cg.ci(arg3) + ")L" + ret + ";"); 749 mv.visitInsn(ARETURN); 750 mv.visitMaxs(5, 3); 751 c = endCall(cw,mv,mname); 752 } 753 FastInvocationCallback ic = (FastInvocationCallback)c.newInstance(); 754 ic.setArity(Arity.fixed(3)); 755 return ic; 756 } catch(IllegalArgumentException e) { 757 throw e; 758 } catch(Exception e) { 759 throw new IllegalArgumentException (e.getMessage()); 760 } 761 } 762 763 public Callback getFastOptMethod(String method) { 764 String mname = type.getName() + "Invoker" + method + "xx1"; 765 String mnamePath = typePath + "Invoker" + method + "xx1"; 766 Class c = tryClass(mname); 767 try { 768 if(c == null) { 769 String ret = getReturnName(method,new Class []{IRubyObject[].class}); 770 ClassWriter cw = createCtorFast(mnamePath); 771 MethodVisitor mv = startCallFast(cw); 772 mv.visitVarInsn(ALOAD, 2); 773 mv.visitTypeInsn(CHECKCAST, "[" + IRUB_ID); 774 mv.visitTypeInsn(CHECKCAST, "[" + IRUB_ID); 775 mv.visitMethodInsn(INVOKEVIRTUAL, typePath, method, "([" + IRUB_ID + ")L" + ret + ";"); 776 mv.visitInsn(ARETURN); 777 mv.visitMaxs(2, 3); 778 c = endCall(cw,mv,mname); 779 } 780 FastInvocationCallback ic = (FastInvocationCallback)c.newInstance(); 781 ic.setArity(Arity.optional()); 782 return ic; 783 } catch(IllegalArgumentException e) { 784 throw e; 785 } catch(Exception e) { 786 throw new IllegalArgumentException (e.getMessage()); 787 } 788 } 789 790 public Callback getFastOptSingletonMethod(String method) { 791 String mname = type.getName() + "InvokerS" + method + "xx1"; 792 String mnamePath = typePath + "InvokerS" + method + "xx1"; 793 Class c = tryClass(mname); 794 try { 795 if(c == null) { 796 String ret = getReturnName(method,new Class []{RubyKernel.IRUBY_OBJECT,IRubyObject[].class}); 797 ClassWriter cw = createCtorFast(mnamePath); 798 MethodVisitor mv = startCallSFast(cw); 799 mv.visitVarInsn(ALOAD, 2); 800 mv.visitTypeInsn(CHECKCAST, "[" + IRUB_ID); 801 mv.visitTypeInsn(CHECKCAST, "[" + IRUB_ID); 802 mv.visitMethodInsn(INVOKESTATIC, typePath, method, "(" + IRUB_ID + "[" + IRUB_ID + ")L"+ret+";"); 803 mv.visitInsn(ARETURN); 804 mv.visitMaxs(2, 3); 805 c = endCall(cw,mv,mname); 806 } 807 FastInvocationCallback ic = (FastInvocationCallback)c.newInstance(); 808 ic.setArity(Arity.optional()); 809 return ic; 810 } catch(IllegalArgumentException e) { 811 throw e; 812 } catch(Exception e) { 813 throw new IllegalArgumentException (e.getMessage()); 814 } 815 } 816 } | Popular Tags |