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