1 28 package org.jruby.compiler; 29 30 import java.util.HashMap ; 31 import java.util.Iterator ; 32 import java.util.Map ; 33 34 import org.jruby.Ruby; 35 import org.jruby.ast.AliasNode; 36 import org.jruby.ast.AndNode; 37 import org.jruby.ast.ArgsCatNode; 38 import org.jruby.ast.ArgsNode; 39 import org.jruby.ast.ArgsPushNode; 40 import org.jruby.ast.ArrayNode; 41 import org.jruby.ast.AttrAssignNode; 42 import org.jruby.ast.BackRefNode; 43 import org.jruby.ast.BeginNode; 44 import org.jruby.ast.BignumNode; 45 import org.jruby.ast.BlockArgNode; 46 import org.jruby.ast.BlockNode; 47 import org.jruby.ast.BlockPassNode; 48 import org.jruby.ast.BreakNode; 49 import org.jruby.ast.CallNode; 50 import org.jruby.ast.CaseNode; 51 import org.jruby.ast.ClassNode; 52 import org.jruby.ast.ClassVarAsgnNode; 53 import org.jruby.ast.ClassVarDeclNode; 54 import org.jruby.ast.ClassVarNode; 55 import org.jruby.ast.Colon2Node; 56 import org.jruby.ast.Colon3Node; 57 import org.jruby.ast.ConstDeclNode; 58 import org.jruby.ast.ConstNode; 59 import org.jruby.ast.DAsgnNode; 60 import org.jruby.ast.DRegexpNode; 61 import org.jruby.ast.DStrNode; 62 import org.jruby.ast.DSymbolNode; 63 import org.jruby.ast.DVarNode; 64 import org.jruby.ast.DXStrNode; 65 import org.jruby.ast.DefinedNode; 66 import org.jruby.ast.DefnNode; 67 import org.jruby.ast.DefsNode; 68 import org.jruby.ast.DotNode; 69 import org.jruby.ast.EnsureNode; 70 import org.jruby.ast.EvStrNode; 71 import org.jruby.ast.FCallNode; 72 import org.jruby.ast.FalseNode; 73 import org.jruby.ast.FixnumNode; 74 import org.jruby.ast.FlipNode; 75 import org.jruby.ast.FloatNode; 76 import org.jruby.ast.ForNode; 77 import org.jruby.ast.GlobalAsgnNode; 78 import org.jruby.ast.GlobalVarNode; 79 import org.jruby.ast.HashNode; 80 import org.jruby.ast.IfNode; 81 import org.jruby.ast.InstAsgnNode; 82 import org.jruby.ast.InstVarNode; 83 import org.jruby.ast.IterNode; 84 import org.jruby.ast.LocalAsgnNode; 85 import org.jruby.ast.LocalVarNode; 86 import org.jruby.ast.Match2Node; 87 import org.jruby.ast.Match3Node; 88 import org.jruby.ast.MatchNode; 89 import org.jruby.ast.ModuleNode; 90 import org.jruby.ast.MultipleAsgnNode; 91 import org.jruby.ast.NewlineNode; 92 import org.jruby.ast.NextNode; 93 import org.jruby.ast.NilNode; 94 import org.jruby.ast.Node; 95 import org.jruby.ast.NotNode; 96 import org.jruby.ast.NthRefNode; 97 import org.jruby.ast.OpAsgnAndNode; 98 import org.jruby.ast.OpAsgnNode; 99 import org.jruby.ast.OpAsgnOrNode; 100 import org.jruby.ast.OpElementAsgnNode; 101 import org.jruby.ast.OptNNode; 102 import org.jruby.ast.OrNode; 103 import org.jruby.ast.PostExeNode; 104 import org.jruby.ast.RedoNode; 105 import org.jruby.ast.RegexpNode; 106 import org.jruby.ast.RescueBodyNode; 107 import org.jruby.ast.RescueNode; 108 import org.jruby.ast.RetryNode; 109 import org.jruby.ast.ReturnNode; 110 import org.jruby.ast.RootNode; 111 import org.jruby.ast.SClassNode; 112 import org.jruby.ast.SValueNode; 113 import org.jruby.ast.SelfNode; 114 import org.jruby.ast.SplatNode; 115 import org.jruby.ast.StrNode; 116 import org.jruby.ast.SuperNode; 117 import org.jruby.ast.SymbolNode; 118 import org.jruby.ast.ToAryNode; 119 import org.jruby.ast.TrueNode; 120 import org.jruby.ast.UndefNode; 121 import org.jruby.ast.UntilNode; 122 import org.jruby.ast.VAliasNode; 123 import org.jruby.ast.VCallNode; 124 import org.jruby.ast.WhenNode; 125 import org.jruby.ast.WhileNode; 126 import org.jruby.ast.XStrNode; 127 import org.jruby.ast.YieldNode; 128 import org.jruby.ast.ZArrayNode; 129 import org.jruby.ast.ZSuperNode; 130 import org.jruby.ast.visitor.NodeVisitor; 131 import org.jruby.evaluator.Instruction; 132 import org.jruby.internal.runtime.methods.MultiStub; 133 import org.jruby.internal.runtime.methods.MultiStubMethod; 134 import org.jruby.runtime.Arity; 135 import org.jruby.runtime.Visibility; 136 import org.jruby.util.JRubyClassLoader; 137 import org.objectweb.asm.ClassWriter; 138 import org.objectweb.asm.Label; 139 import org.objectweb.asm.MethodVisitor; 140 import org.objectweb.asm.Opcodes; 141 import org.objectweb.asm.Type; 142 143 public class InstructionCompiler2 implements NodeVisitor { 144 private static final String RUBYMODULE = "org/jruby/RubyModule"; 145 146 private static final String RUBY = "org/jruby/Ruby"; 147 148 private static final String IRUBYOBJECT = "org/jruby/runtime/builtin/IRubyObject"; 149 150 152 private static final String THREADCONTEXT = "org/jruby/runtime/ThreadContext"; 153 154 private static final boolean EXPERIMENTAL_SOURCING = true; 155 156 private ArgsNode args; 157 private ClassWriter cv; 158 private MethodVisitor mv; 159 160 private int lastLine = 0; 161 162 private boolean runtimeLoaded; 163 164 Map classWriters = new HashMap (); 165 ClassWriter currentMultiStub = null; 166 int multiStubIndex = -1; 167 int multiStubCount = -1; 168 169 private String classname; 170 171 private String sourceName; 172 173 public InstructionCompiler2() { 174 } 175 176 public void closeOutMultiStub() { 177 if (currentMultiStub != null) { 178 while (multiStubIndex < 9) { 179 MethodVisitor multiStubMethod = createNewMethod(); 180 multiStubMethod.visitCode(); 181 multiStubMethod.visitInsn(Opcodes.ACONST_NULL); 182 multiStubMethod.visitInsn(Opcodes.ARETURN); 183 multiStubMethod.visitMaxs(1, 1); 184 multiStubMethod.visitEnd(); 185 } 186 } 187 } 188 189 public void defineModuleFunction(Ruby runtime, String module, String name, MultiStub stub, int index, Arity arity, Visibility visibility) { 190 runtime.getModule(module).addMethod(name, new MultiStubMethod(stub, index, runtime.getModule(module), arity, visibility)); 191 } 192 193 public String [] compile(String classname, String sourceName, Node node) { 194 cv = new ClassWriter(true); 195 if (classname.startsWith("-e")) { 196 classname = classname.replaceAll("-e", "DashE"); 197 } 198 classWriters.put(classname, cv); 199 this.classname = classname; 200 this.sourceName = sourceName; 201 202 cv.visit(Opcodes.V1_2, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, 203 classname, null, "java/lang/Object", new String [] {"org/jruby/ast/executable/Script"}); 204 cv.visitSource(sourceName, null); 205 206 mv = cv.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null); 207 mv.visitCode(); 208 mv.visitVarInsn(Opcodes.ALOAD, 0); 209 mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", 210 "()V"); 211 mv.visitInsn(Opcodes.RETURN); 212 mv.visitMaxs(1, 1); 213 mv.visitEnd(); 214 215 mv = createNewMethod(); 217 String className = classname + "$MultiStub" + multiStubCount; 218 String methodName = "method" + multiStubIndex; 219 mv.visitCode(); 220 221 try { 222 node.accept(this); 223 } catch (NotCompilableException nce) { 224 throw nce; 226 } 227 228 mv.visitInsn(Opcodes.ARETURN); 229 mv.visitMaxs(1, 1); mv.visitEnd(); 231 232 runtimeLoaded = false; 233 234 closeOutMultiStub(); 235 236 mv = cv.visitMethod(Opcodes.ACC_PUBLIC, "run", "(Lorg/jruby/runtime/ThreadContext;Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject;", null, null); 238 mv.visitTypeInsn(Opcodes.NEW, className); 239 mv.visitInsn(Opcodes.DUP); 240 mv.visitMethodInsn(Opcodes.INVOKESPECIAL, className, "<init>", "()V"); 241 mv.visitVarInsn(Opcodes.ALOAD, 1); 242 mv.visitVarInsn(Opcodes.ALOAD, 2); 243 mv.visitInsn(Opcodes.ACONST_NULL); 244 mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, methodName, "(Lorg/jruby/runtime/ThreadContext;Lorg/jruby/runtime/builtin/IRubyObject;[Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject;"); 245 mv.visitInsn(Opcodes.ARETURN); 246 mv.visitMaxs(1, 1); 247 mv.visitEnd(); 248 249 return new String [] {className, methodName}; 250 } 251 252 public Class loadClasses(JRubyClassLoader loader) throws ClassNotFoundException { 253 for (Iterator iter = classWriters.entrySet().iterator(); iter.hasNext();) { 254 Map.Entry entry = (Map.Entry )iter.next(); 255 String key = (String )entry.getKey(); 256 ClassWriter writer = (ClassWriter)entry.getValue(); 257 258 loader.defineClass(key.replaceAll("/", "."), writer.toByteArray()); 259 } 260 261 return loader.loadClass(classname.replaceAll("/", ".")); 262 } 263 264 public Instruction visitAliasNode(AliasNode iVisited) { 266 lineNumber(iVisited); 267 getRubyClass(); 268 mv.visitInsn(Opcodes.DUP); 269 mv.visitInsn(Opcodes.DUP); 270 Label l1 = new Label(); 271 mv.visitJumpInsn(Opcodes.IFNONNULL, l1); 272 newTypeError("no class to make alias"); 273 mv.visitInsn(Opcodes.ATHROW); 274 275 mv.visitLabel(l1); 276 loadThreadContext(); 277 defineAlias(iVisited.getNewName(), iVisited.getOldName()); 278 mv.visitLdcInsn("method_added"); 279 newSymbol(iVisited.getNewName()); 280 invokeRubyModule("callMethod", "(Lorg/jruby/runtime/ThreadContext;Ljava/lang/String;Lorg/jruby/RubySymbol;)Lorg/jruby/runtime/builtin/IRubyObject;"); 281 282 return null; 283 } 284 285 private void newSymbol(String name) { 286 loadRuntime(); 287 mv.visitLdcInsn(name); 288 invokeRuby("newSymbol", "()Lorg/jruby/RubySymbol;"); 289 } 290 291 private void defineAlias(String newName, String oldName) { 292 mv.visitLdcInsn(newName); 293 mv.visitLdcInsn(oldName); 294 invokeRubyModule("defineAlias", "(Ljava/lang/String;Ljava/lang/String;)V"); 295 } 296 297 private void newTypeError(String error) { 298 loadRuntime(); 299 mv.visitLdcInsn(error); 300 invokeRuby("newTypeError", "(Ljava/lang/String;)Lorg/jruby/exceptions/RaiseException;"); 301 } 302 303 public Instruction visitAndNode(AndNode iVisited) { 304 lineNumber(iVisited); 305 iVisited.getFirstNode().accept(this); 306 mv.visitInsn(Opcodes.DUP); 307 invokeIRubyObject("isTrue", "()B"); 308 Label l1 = new Label(); 309 mv.visitJumpInsn(Opcodes.IFEQ, l1); 310 mv.visitInsn(Opcodes.POP); iVisited.getSecondNode().accept(this); 312 mv.visitLabel(l1); 313 314 return null; 315 } 316 317 private void invokeIRubyObject(String methodName, String signature) { 318 mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, IRUBYOBJECT, methodName, signature); 319 } 320 321 private void invokeRuby(String methodName, String signature) { 322 mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, RUBY, methodName, signature); 323 } 324 325 private void invokeThreadContext(String methodName, String signature) { 326 mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, THREADCONTEXT, methodName, signature); 327 } 328 329 private void invokeRubyModule(String methodName, String signature) { 330 mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, RUBYMODULE, methodName, signature); 331 } 332 333 public Instruction visitArgsNode(ArgsNode iVisited) { 334 return null; 336 } 337 338 public Instruction visitArgsCatNode(ArgsCatNode iVisited) { 339 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 340 } 341 342 private interface ValueCallback { 343 public void putValueOnStack(Object sourceArray, int index); 344 } 345 346 public Instruction visitArrayNode(ArrayNode iVisited) { 347 lineNumber(iVisited); 348 loadRuntime(); 349 350 ValueCallback callback = new ValueCallback() { 351 public void putValueOnStack(Object sourceArray, int index) { 352 Node node = (Node)((Object [])sourceArray)[index]; 353 node.accept(InstructionCompiler2.this); 354 } 355 }; 356 buildObjectArray(IRUBYOBJECT, iVisited.childNodes().toArray(), callback); 357 358 invokeRuby("newArray", "([Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/RubyArray;"); 359 360 return null; 361 } 362 363 private void buildObjectArray(String type, Object [] sourceArray, ValueCallback callback) { 364 mv.visitLdcInsn(new Integer (sourceArray.length)); 365 mv.visitTypeInsn(Opcodes.ANEWARRAY, type); 366 367 for (int i = 0; i < sourceArray.length; i++) { 368 mv.visitInsn(Opcodes.DUP); 369 mv.visitLdcInsn(new Integer (i)); 370 371 callback.putValueOnStack(sourceArray, i); 372 373 mv.visitInsn(Opcodes.AASTORE); 374 i++; 375 } 376 } 377 378 private void buildPrimitiveArray(Type type, Object sourceArray, int length, ValueCallback callback) { 379 mv.visitLdcInsn(new Integer (length)); 380 mv.visitTypeInsn(Opcodes.NEWARRAY, type.getDescriptor()); 381 382 for (int i = 0; i < length; i++) { 383 mv.visitInsn(Opcodes.DUP); 384 mv.visitLdcInsn(new Integer (i)); 385 386 callback.putValueOnStack(sourceArray, i); 387 388 if (type.equals(Type.BYTE_TYPE) || type.equals(Type.BOOLEAN_TYPE)) { 389 mv.visitInsn(Opcodes.BASTORE); 390 } else if (type.equals(Type.CHAR_TYPE)) { 391 mv.visitInsn(Opcodes.CASTORE); 392 } else if (type.equals(Type.INT_TYPE)) { 393 mv.visitInsn(Opcodes.IASTORE); 394 } else if (type.equals(Type.LONG_TYPE)) { 395 mv.visitInsn(Opcodes.LASTORE); 396 } else if (type.equals(Type.FLOAT_TYPE)) { 397 mv.visitInsn(Opcodes.FASTORE); 398 } else if (type.equals(Type.DOUBLE_TYPE)) { 399 mv.visitInsn(Opcodes.DASTORE); 400 } 401 i++; 402 } 403 } 404 405 public Instruction visitArgsPushNode(ArgsPushNode iVisited) { 406 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 407 } 408 409 public Instruction visitAttrAssignNode(AttrAssignNode iVisited) { 411 lineNumber(iVisited); 412 loadThreadContext(); invokeThreadContext("beginCallArgs", "()V"); 415 iVisited.getReceiverNode().accept(this); 419 setupArgs(iVisited.getArgsNode()); 422 loadThreadContext(); invokeThreadContext("endCallArgs", "()V"); 425 mv.visitInsn(Opcodes.SWAP); 427 mv.visitInsn(Opcodes.DUP); 429 loadThreadContext(); 430 invokeThreadContext("getFrameSelf", "()Lorg/jruby/runtime/builtin/IRubyObject;"); 432 Label l1 = new Label(); 433 Label l2 = new Label(); 434 435 mv.visitJumpInsn(Opcodes.IF_ACMPEQ, l1); mv.visitFieldInsn(Opcodes.GETSTATIC, "org/jruby/runtime/CallType", "NORMAL", "Lorg/jruby/runtime/CallType;"); 438 mv.visitJumpInsn(Opcodes.GOTO, l2); 439 mv.visitLabel(l1); 440 mv.visitFieldInsn(Opcodes.GETSTATIC, "org/jruby/runtime/CallType", "VARIABLE", "Lorg/jruby/runtime/CallType;"); 441 mv.visitLabel(l2); 442 443 445 mv.visitInsn(Opcodes.SWAP); 448 loadThreadContext(); mv.visitInsn(Opcodes.DUP2_X2); mv.visitInsn(Opcodes.POP2); 452 mv.visitLdcInsn(iVisited.getName()); 455 mv.visitInsn(Opcodes.DUP_X2); 458 mv.visitInsn(Opcodes.POP); 461 invokeIRubyObject("callMethod", "(Lorg/jruby/runtime/ThreadContext;Ljava/lang/String;[Lorg/jruby/runtime/builtin/IRubyObject;Lorg/jruby/runtime/CallType;)Lorg/jruby/runtime/builtin/IRubyObject;"); 462 463 return null; 464 } 465 466 public Instruction visitBackRefNode(BackRefNode iVisited) { 467 loadThreadContext(); 468 mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, THREADCONTEXT, "getBackref", "()Lorg/jruby/runtime/builtin/IRubyObject;"); 469 Label l1 = new Label(); 470 Label l2 = new Label(); 471 Label l3 = new Label(); 472 Label l4 = new Label(); 473 Label l5 = new Label(); 474 Label lafter = new Label(); 475 mv.visitLookupSwitchInsn(lafter, new int[] { '~', '&', '`', '\\', '+' }, new Label[] { l1, l2, l3, l4, l5 }); 476 mv.visitLabel(l1); 477 mv.visitJumpInsn(Opcodes.GOTO, lafter); 479 480 mv.visitLabel(l2); 481 mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/jruby/RubyRegexp", "last_match", "(Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject;"); 483 mv.visitJumpInsn(Opcodes.GOTO, lafter); 484 485 mv.visitLabel(l3); 486 mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/jruby/RubyRegexp", "match_pre", "(Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject;"); 488 mv.visitJumpInsn(Opcodes.GOTO, lafter); 489 490 mv.visitLabel(l4); 491 mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/jruby/RubyRegexp", "match_post", "(Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject;"); 493 mv.visitJumpInsn(Opcodes.GOTO, lafter); 494 495 mv.visitLabel(l5); 496 mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/jruby/RubyRegexp", "match_last", "(Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject;"); 498 499 mv.visitLabel(lafter); 500 501 return null; 502 } 503 504 public Instruction visitBeginNode(BeginNode iVisited) { 505 iVisited.getBodyNode().accept(this); 506 507 return null; 508 } 509 510 public Instruction visitBignumNode(BignumNode iVisited) { 511 lineNumber(iVisited); 513 loadRuntime(); 514 mv.visitTypeInsn(Opcodes.NEW, "java/math/BigInteger"); 515 mv.visitInsn(Opcodes.DUP); 516 mv.visitLdcInsn(iVisited.getValue().toString()); 517 mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/math/BigInteger", "<init>", "(Ljava/lang/String;)V"); 518 519 mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/jruby/RubyBignum", "newBignum", "(Lorg/jruby/Ruby;Ljava/math/BigInteger;)Lorg/jruby/RubyBignum;"); 520 521 return null; 522 } 523 524 public Instruction visitBlockArgNode(BlockArgNode iVisited) { 525 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 526 } 527 528 public Instruction visitBlockNode(BlockNode iVisited) { 529 lineNumber(iVisited); 530 for (Iterator iter = iVisited.childNodes().iterator(); iter.hasNext();) { 531 Node n = (Node)iter.next(); 532 533 n.accept(this); 534 535 if (iter.hasNext()) { 536 mv.visitInsn(Opcodes.POP); 538 } 539 } 540 541 return null; 542 } 543 544 public Instruction visitBlockPassNode(BlockPassNode iVisited) { 545 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 546 } 547 548 public Instruction visitBreakNode(BreakNode iVisited) { 549 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 550 } 551 552 public Instruction visitConstDeclNode(ConstDeclNode iVisited) { 553 lineNumber(iVisited); 555 556 iVisited.getValueNode().accept(this); 557 558 if (iVisited.getConstNode() != null) { 559 iVisited.getConstNode().accept(this); 560 } else { 561 getRubyClass(); 562 Label l1 = new Label(); 563 564 mv.visitJumpInsn(Opcodes.IFNONNULL, l1); 565 566 newTypeError("no class/module to define constant"); 567 mv.visitInsn(Opcodes.ATHROW); 568 569 mv.visitLabel(l1); 570 571 peekCRef(); 572 } 573 574 mv.visitTypeInsn(Opcodes.CHECKCAST, RUBYMODULE); 575 576 mv.visitInsn(Opcodes.SWAP); 577 mv.visitLdcInsn(iVisited.getName()); 578 mv.visitInsn(Opcodes.SWAP); 579 invokeRubyModule("setConstant", "(Ljava/lang/String;Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject;"); 580 581 return null; 582 } 583 584 private void peekCRef() { 585 loadThreadContext(); 586 invokeThreadContext("peekCRef", "()Lorg/jruby/util/collections/SinglyLinkedList;"); 587 mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/jruby/util/collections/SingleLinkedList", "getValue", "()Ljava/lang/Object;"); 588 } 589 590 public Instruction visitClassVarAsgnNode(ClassVarAsgnNode iVisited) { 591 lineNumber(iVisited); 592 593 iVisited.getValueNode().accept(this); 595 596 getCRefClass(); 597 598 mv.visitInsn(Opcodes.DUP); 600 601 Label l1 = new Label(); 602 Label l2 = new Label(); 603 mv.visitJumpInsn(Opcodes.IFNONNULL, l1); 604 605 mv.visitInsn(Opcodes.POP); 608 loadSelf(); 609 invokeIRubyObject("getMetaClass", "()Lorg/jruby/RubyClass;"); 610 mv.visitJumpInsn(Opcodes.GOTO, l2); 611 612 mv.visitLabel(l1); 614 mv.visitInsn(Opcodes.DUP); 616 invokeRubyModule("isSingleton", "()Z"); 617 mv.visitJumpInsn(Opcodes.IFEQ, l2); 618 619 mv.visitLdcInsn("__attached__"); 620 invokeIRubyObject("getInstanceVariable", "(Ljava/lang/String;)Lorg/jruby/runtime/builtin/IRubyObject;"); 621 mv.visitTypeInsn(Opcodes.CHECKCAST, RUBYMODULE); 622 623 mv.visitLabel(l2); 624 625 mv.visitInsn(Opcodes.SWAP); 626 mv.visitLdcInsn(iVisited.getName()); 627 mv.visitInsn(Opcodes.SWAP); 628 invokeRubyModule("setClassVar", "(Ljava/lang/String;Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject;"); 629 630 return null; 631 } 632 633 public Instruction visitClassVarDeclNode(ClassVarDeclNode iVisited) { 634 lineNumber(iVisited); 636 637 getRubyClass(); 638 Label l298 = new Label(); 639 mv.visitJumpInsn(Opcodes.IFNONNULL, l298); 640 newTypeError("no class/module to define class variable"); 641 mv.visitInsn(Opcodes.ATHROW); 642 643 mv.visitLabel(l298); 644 getCRefClass(); 645 646 mv.visitLdcInsn(iVisited.getName()); 647 648 iVisited.getValueNode().accept(this); 649 650 invokeRubyModule("setClassVar", "(Ljava/lang/String;Lorg/jruby/runtime/builtin/IRubyObject;)V"); 651 652 loadRuntime(); 653 invokeRuby("getNil", "()Lorg/jruby/runtime/builtin/IRubyObject;"); 654 655 return null; 656 } 657 658 public Instruction visitClassVarNode(ClassVarNode iVisited) { 659 lineNumber(iVisited); 661 662 getCRefClass(); 663 664 mv.visitInsn(Opcodes.DUP); 666 667 Label l1 = new Label(); 668 Label l2 = new Label(); 669 mv.visitJumpInsn(Opcodes.IFNONNULL, l1); 670 671 mv.visitInsn(Opcodes.POP); 673 loadSelf(); 674 invokeIRubyObject("getMetaClass", "()Lorg/jruby/RubyClass;"); 675 mv.visitJumpInsn(Opcodes.GOTO, l2); 676 677 mv.visitLabel(l1); 678 mv.visitInsn(Opcodes.DUP); 680 invokeRubyModule("isSingleton", "()Z"); 681 mv.visitJumpInsn(Opcodes.IFEQ, l2); 682 683 mv.visitLdcInsn("__attached__"); 684 invokeIRubyObject("getInstanceVariable", "(Ljava/lang/String;)Lorg/jruby/runtime/builtin/IRubyObject;"); 685 mv.visitTypeInsn(Opcodes.CHECKCAST, RUBYMODULE); 686 687 mv.visitLabel(l2); 688 689 mv.visitLdcInsn(iVisited.getName()); 690 invokeRubyModule("getClassVar", "(Ljava/lang/String;)Lorg/jruby/runtime/builtin/IRubyObject;"); 691 692 return null; 693 } 694 695 public Instruction visitCallNode(CallNode iVisited) { 696 lineNumber(iVisited); 697 loadThreadContext(); invokeThreadContext("beginCallArgs", "()V"); 700 iVisited.getReceiverNode().accept(this); 704 setupArgs(iVisited.getArgsNode()); 707 loadThreadContext(); invokeThreadContext("endCallArgs", "()V"); 710 mv.visitInsn(Opcodes.SWAP); 712 mv.visitInsn(Opcodes.DUP); 714 loadThreadContext(); 715 invokeThreadContext("getFrameSelf", "()Lorg/jruby/runtime/builtin/IRubyObject;"); 717 Label l1 = new Label(); 718 Label l2 = new Label(); 719 720 mv.visitJumpInsn(Opcodes.IF_ACMPEQ, l1); mv.visitFieldInsn(Opcodes.GETSTATIC, "org/jruby/runtime/CallType", "NORMAL", "Lorg/jruby/runtime/CallType;"); 723 mv.visitJumpInsn(Opcodes.GOTO, l2); 724 mv.visitLabel(l1); 725 mv.visitFieldInsn(Opcodes.GETSTATIC, "org/jruby/runtime/CallType", "VARIABLE", "Lorg/jruby/runtime/CallType;"); 726 mv.visitLabel(l2); 727 728 730 mv.visitInsn(Opcodes.SWAP); 733 loadThreadContext(); mv.visitInsn(Opcodes.DUP2_X2); mv.visitInsn(Opcodes.POP2); 737 mv.visitLdcInsn(iVisited.getName()); 740 mv.visitInsn(Opcodes.DUP_X2); 743 mv.visitInsn(Opcodes.POP); 746 invokeIRubyObject("callMethod", "(Lorg/jruby/runtime/ThreadContext;Ljava/lang/String;[Lorg/jruby/runtime/builtin/IRubyObject;Lorg/jruby/runtime/CallType;)Lorg/jruby/runtime/builtin/IRubyObject;"); 747 748 return null; 749 } 750 751 public Instruction visitCaseNode(CaseNode iVisited) { 752 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 753 } 754 755 public Instruction visitClassNode(ClassNode iVisited) { 756 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 757 } 758 759 public Instruction visitColon2Node(Colon2Node iVisited) { 760 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 761 } 762 763 public Instruction visitColon3Node(Colon3Node iVisited) { 764 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 765 } 766 767 public Instruction visitConstNode(ConstNode iVisited) { 768 lineNumber(iVisited); 769 770 loadThreadContext(); 771 mv.visitLdcInsn(iVisited.getName()); 772 invokeThreadContext("getConstant", "(Ljava/lang/String;)Lorg/jruby/runtime/builtin/IRubyObject;"); 773 774 return null; 775 } 776 777 public Instruction visitDAsgnNode(DAsgnNode iVisited) { 778 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 779 } 780 781 public Instruction visitDRegxNode(DRegexpNode iVisited) { 782 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 783 } 784 785 public Instruction visitDStrNode(DStrNode iVisited) { 786 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 787 } 788 789 public Instruction visitDSymbolNode(DSymbolNode iVisited) { 790 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 791 } 792 793 public Instruction visitDVarNode(DVarNode iVisited) { 794 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 795 } 796 797 public Instruction visitDXStrNode(DXStrNode iVisited) { 798 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 799 } 800 801 public Instruction visitDefinedNode(DefinedNode iVisited) { 802 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 803 } 804 805 public MethodVisitor createNewMethod() { 806 if (currentMultiStub == null || multiStubIndex == 9) { 808 if (currentMultiStub != null) { 809 currentMultiStub.visitEnd(); 811 } 812 813 multiStubCount++; 814 815 currentMultiStub = new ClassWriter(true); 816 currentMultiStub.visit(Opcodes.V1_2, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER + Opcodes.ACC_STATIC, 817 classname + "$MultiStub" + multiStubCount, null, "java/lang/Object", new String [] {"org/jruby/internal/runtime/methods/MultiStub"}); 818 cv.visitInnerClass(classname + "$MultiStub" + multiStubCount, classname, "MultiStub" + multiStubCount, Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC); 819 multiStubIndex = 0; 820 classWriters.put(classname + "$MultiStub" + multiStubCount, currentMultiStub); 821 currentMultiStub.visitSource(sourceName, null); 822 823 MethodVisitor stubConstructor = currentMultiStub.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null); 824 stubConstructor.visitCode(); 825 stubConstructor.visitVarInsn(Opcodes.ALOAD, 0); 826 stubConstructor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", 827 "()V"); 828 stubConstructor.visitInsn(Opcodes.RETURN); 829 stubConstructor.visitMaxs(1, 1); 830 stubConstructor.visitEnd(); 831 } else { 832 multiStubIndex++; 833 } 834 835 return currentMultiStub.visitMethod(Opcodes.ACC_PUBLIC, "method" + multiStubIndex, "(Lorg/jruby/runtime/ThreadContext;Lorg/jruby/runtime/builtin/IRubyObject;[Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject;", null, null); 836 } 837 838 public Instruction visitDefnNode(DefnNode iVisited) { 839 MethodVisitor oldMethod = mv; 841 boolean oldRuntimeLoaded = runtimeLoaded; 842 843 runtimeLoaded = false; 844 845 mv = createNewMethod(); 846 mv.visitCode(); 847 848 args = (ArgsNode)iVisited.getArgsNode(); 850 851 mv.visitLdcInsn(new Integer (iVisited.getScope().getNumberOfVariables())); 852 mv.visitTypeInsn(Opcodes.ANEWARRAY, "org/jruby/runtime/builtin/IRubyObject"); 853 mv.visitInsn(Opcodes.DUP); 854 mv.visitVarInsn(Opcodes.ASTORE, 4); 856 mv.visitVarInsn(Opcodes.ALOAD, 3); 857 mv.visitInsn(Opcodes.SWAP); 858 mv.visitLdcInsn(new Integer (0)); 859 mv.visitInsn(Opcodes.SWAP); 860 mv.visitLdcInsn(new Integer (0)); 861 mv.visitLdcInsn(new Integer (args.getArity().getValue())); 862 mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V"); 863 864 try { 865 iVisited.getBodyNode().accept(this); 866 } catch (NotCompilableException nce) { 867 throw nce; 869 } 870 871 mv.visitMaxs(1, 1); mv.visitInsn(Opcodes.ARETURN); 873 mv.visitEnd(); 874 875 runtimeLoaded = oldRuntimeLoaded; 876 877 mv = oldMethod; 878 879 getRubyClass(); 881 Label l335 = new Label(); 882 mv.visitJumpInsn(Opcodes.IFNONNULL, l335); 884 newTypeError("No class to add method."); 885 mv.visitInsn(Opcodes.ATHROW); 886 mv.visitLabel(l335); 887 888 Label l338 = new Label(); 889 890 if (iVisited.getName().equals("initialize")) { 892 getRubyClass(); 894 loadRuntime(); 895 invokeRuby("getObject", "()Lorg/jruby/RubyClass;"); 896 mv.visitJumpInsn(Opcodes.IF_ACMPNE, l338); 898 loadRuntime(); 899 invokeRuby("getWarnings", "()Lorg/jruby/common/RubyWarnings;"); 901 mv.visitLdcInsn("redefining Object#initialize may cause infinite loop"); 902 mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/jruby/common/RubyWarnings", "warn", "(Ljava/lang/String;)V"); 903 } 904 905 mv.visitLabel(l338); 906 getRubyClass(); 921 mv.visitTypeInsn(Opcodes.NEW, "org/jruby/internal/runtime/methods/MultiStubMethod"); 922 mv.visitInsn(Opcodes.DUP); 923 mv.visitTypeInsn(Opcodes.NEW, classname + "$MultiStub" + multiStubCount); 924 mv.visitInsn(Opcodes.DUP); 925 mv.visitMethodInsn(Opcodes.INVOKESPECIAL, classname + "$MultiStub" + multiStubCount, "<init>", "()V"); 926 mv.visitLdcInsn(new Integer (multiStubIndex)); 927 getRubyClass(); 928 mv.visitLdcInsn(new Integer (args.getArity().getValue())); 933 mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/jruby/runtime/Arity", "createArity", "(I)Lorg/jruby/runtime/Arity;"); 934 getCurrentVisibility(); 935 mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "org/jruby/internal/runtime/methods/MultiStubMethod", "<init>", "(Lorg/jruby/internal/runtime/methods/MultiStub;ILorg/jruby/RubyModule;Lorg/jruby/runtime/Arity;Lorg/jruby/runtime/Visibility;)V"); 936 937 mv.visitLdcInsn(iVisited.getName()); 938 mv.visitInsn(Opcodes.SWAP); 940 mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/jruby/RubyModule", "addMethod", "(Ljava/lang/String;Lorg/jruby/runtime/ICallable;)V"); 941 loadRuntime(); 1007 invokeRuby("getNil", "()Lorg/jruby/runtime/builtin/IRubyObject;"); 1008 1009 return null; 1010 } 1011 1012 private void getCurrentVisibility() { 1013 loadThreadContext(); 1014 invokeThreadContext("getCurrentVisibility", "()Lorg/jruby/runtime/Visibility;"); 1015 } 1016 1017 public Instruction visitDefsNode(DefsNode iVisited) { 1018 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1019 } 1020 1021 public Instruction visitDotNode(DotNode iVisited) { 1022 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1023 } 1024 1025 public Instruction visitEnsureNode(EnsureNode iVisited) { 1026 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1027 } 1028 1029 public Instruction visitEvStrNode(EvStrNode iVisited) { 1030 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1031 } 1032 1033 public Instruction visitFCallNode(FCallNode iVisited) { 1034 lineNumber(iVisited); 1035 loadThreadContext(); 1036 invokeThreadContext("getFrameSelf", "()Lorg/jruby/runtime/builtin/IRubyObject;"); 1038 mv.visitLdcInsn(iVisited.getName()); 1040 loadThreadContext(); invokeThreadContext("beginCallArgs", "()V"); 1043 setupArgs(iVisited.getArgsNode()); 1046 loadThreadContext(); 1047 invokeThreadContext("endCallArgs", "()V"); 1049 loadThreadContext(); 1050 mv.visitInsn(Opcodes.DUP_X2); mv.visitInsn(Opcodes.POP); 1053 mv.visitFieldInsn(Opcodes.GETSTATIC, "org/jruby/runtime/CallType", "FUNCTIONAL", "Lorg/jruby/runtime/CallType;"); 1055 invokeIRubyObject("callMethod", "(Lorg/jruby/runtime/ThreadContext;Ljava/lang/String;[Lorg/jruby/runtime/builtin/IRubyObject;Lorg/jruby/runtime/CallType;)Lorg/jruby/runtime/builtin/IRubyObject;"); 1056 1057 return null; 1058 } 1059 1060 public Instruction visitFalseNode(FalseNode iVisited) { 1061 lineNumber(iVisited); 1062 loadRuntime(); 1063 invokeRuby("getFalse", "()Lorg/jruby/RubyBoolean;"); 1064 1065 return null; 1066 } 1067 1068 public Instruction visitFixnumNode(FixnumNode iVisited) { 1069 lineNumber(iVisited); 1070 loadThreadContext(); 1071 mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, 1072 THREADCONTEXT, "getRuntime", 1073 "()Lorg/jruby/Ruby;"); 1074 mv.visitLdcInsn(new Long (iVisited.getValue())); 1075 invokeRuby("newFixnum", "(J)Lorg/jruby/RubyFixnum;"); 1076 1077 return null; 1078 } 1079 1080 public Instruction visitFlipNode(FlipNode iVisited) { 1081 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1082 } 1083 1084 public Instruction visitFloatNode(FloatNode iVisited) { 1085 lineNumber(iVisited); 1086 loadRuntime(); 1087 mv.visitLdcInsn(new Double (iVisited.getValue())); 1088 mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/jruby/RubyFloat", "newFloat", "(Lorg/jruby/Ruby;D)Lorg/jruby/RubyFloat;"); 1089 1090 return null; 1091 } 1092 1093 public Instruction visitForNode(ForNode iVisited) { 1094 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1095 } 1096 1097 public Instruction visitGlobalAsgnNode(GlobalAsgnNode iVisited) { 1098 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1099 } 1100 1101 public Instruction visitGlobalVarNode(GlobalVarNode iVisited) { 1102 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1103 } 1104 1105 public Instruction visitHashNode(HashNode iVisited) { 1106 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1107 } 1108 1109 public Instruction visitInstAsgnNode(InstAsgnNode iVisited) { 1110 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1111 } 1112 1113 public Instruction visitInstVarNode(InstVarNode iVisited) { 1114 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1115 } 1116 1117 public Instruction visitIfNode(IfNode iVisited) { 1118 lineNumber(iVisited); 1119 Label afterJmp = new Label(); 1120 Label falseJmp = new Label(); 1121 1122 iVisited.getCondition().accept(this); 1124 1125 invokeIRubyObject("isTrue", "()Z"); 1127 mv.visitJumpInsn(Opcodes.IFEQ, falseJmp); iVisited.getThenBody().accept(this); 1129 mv.visitJumpInsn(Opcodes.GOTO, afterJmp); 1130 1131 mv.visitLabel(falseJmp); 1132 iVisited.getElseBody().accept(this); 1133 1134 mv.visitLabel(afterJmp); 1135 1136 return null; 1137 } 1138 1139 public Instruction visitIterNode(IterNode iVisited) { 1140 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1141 } 1142 1143 public Instruction visitLocalAsgnNode(LocalAsgnNode iVisited) { 1144 lineNumber(iVisited); 1145 1146 iVisited.getValueNode().accept(this); 1147 mv.visitInsn(Opcodes.DUP); 1148 mv.visitVarInsn(Opcodes.ALOAD, 4); 1149 mv.visitInsn(Opcodes.SWAP); 1150 mv.visitLdcInsn(new Integer (iVisited.getIndex())); 1151 mv.visitInsn(Opcodes.SWAP); 1152 mv.visitInsn(Opcodes.AASTORE); 1153 1154 return null; 1155 } 1156 1157 public Instruction visitLocalVarNode(LocalVarNode iVisited) { 1158 lineNumber(iVisited); 1159 int index = iVisited.getIndex(); 1161 1162 if (args != null && (index - 2) < args.getArgsCount()) { 1163 1166 mv.visitVarInsn(Opcodes.ALOAD, 3); 1168 mv.visitLdcInsn(new Integer (index - 2)); 1169 mv.visitInsn(Opcodes.AALOAD); 1170 } else { 1171 mv.visitVarInsn(Opcodes.ALOAD, 4); 1172 mv.visitLdcInsn(new Integer (iVisited.getIndex())); 1173 mv.visitInsn(Opcodes.AALOAD); 1174 } 1175 return null; 1176 } 1177 1178 public Instruction visitMultipleAsgnNode(MultipleAsgnNode iVisited) { 1179 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1180 } 1181 1182 public Instruction visitMatch2Node(Match2Node iVisited) { 1183 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1184 } 1185 1186 public Instruction visitMatch3Node(Match3Node iVisited) { 1187 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1188 } 1189 1190 public Instruction visitMatchNode(MatchNode iVisited) { 1191 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1192 } 1193 1194 public Instruction visitModuleNode(ModuleNode iVisited) { 1195 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1196 } 1197 1198 public Instruction visitNewlineNode(NewlineNode iVisited) { 1199 1201 iVisited.getNextNode().accept(this); 1202 1203 return null; 1204 } 1205 1206 public Instruction visitNextNode(NextNode iVisited) { 1207 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1208 } 1209 1210 public Instruction visitNilNode(NilNode iVisited) { 1211 lineNumber(iVisited); 1212 loadRuntime(); 1213 invokeRuby("getNil", "()Lorg/jruby/runtime/builtin/IRubyObject;"); 1214 1215 return null; 1216 } 1217 1218 public Instruction visitNotNode(NotNode iVisited) { 1219 lineNumber(iVisited); 1220 loadRuntime(); 1221 iVisited.getConditionNode().accept(this); 1222 invokeIRubyObject("isTrue", "()B"); 1223 Label l1 = new Label(); 1224 Label l2 = new Label(); 1225 mv.visitJumpInsn(Opcodes.IFEQ, l1); 1226 invokeRuby("getFalse", "()Lorg/jruby/RubyBoolean;"); 1227 mv.visitLabel(l1); 1228 invokeRuby("getTrue", "()Lorg/jruby/RubyBoolean;"); 1229 mv.visitLabel(l2); 1230 1231 return null; 1232 } 1233 1234 public Instruction visitNthRefNode(NthRefNode iVisited) { 1235 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1236 } 1237 1238 public Instruction visitOpElementAsgnNode(OpElementAsgnNode iVisited) { 1239 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1240 } 1241 1242 public Instruction visitOpAsgnNode(OpAsgnNode iVisited) { 1243 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1244 } 1245 1246 public Instruction visitOpAsgnAndNode(OpAsgnAndNode iVisited) { 1247 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1248 } 1249 1250 public Instruction visitOpAsgnOrNode(OpAsgnOrNode iVisited) { 1251 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1252 } 1253 1254 public Instruction visitOptNNode(OptNNode iVisited) { 1255 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1256 } 1257 1258 public Instruction visitOrNode(OrNode iVisited) { 1259 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1260 } 1261 1262 public Instruction visitPostExeNode(PostExeNode iVisited) { 1263 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1264 } 1265 1266 public Instruction visitRedoNode(RedoNode iVisited) { 1267 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1268 } 1269 1270 public Instruction visitRegexpNode(RegexpNode iVisited) { 1271 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1272 } 1273 1274 public Instruction visitRescueBodyNode(RescueBodyNode iVisited) { 1275 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1276 } 1277 1278 public Instruction visitRescueNode(RescueNode iVisited) { 1279 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1280 } 1281 1282 public Instruction visitRetryNode(RetryNode iVisited) { 1283 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1284 } 1285 1286 public Instruction visitReturnNode(ReturnNode iVisited) { 1287 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1288 } 1289 1290 public Instruction visitRootNode(RootNode iVisited) { 1291 mv.visitLdcInsn(new Integer (iVisited.getStaticScope().getNumberOfVariables())); 1292 mv.visitTypeInsn(Opcodes.ANEWARRAY, "org/jruby/runtime/builtin/IRubyObject"); 1293 mv.visitVarInsn(Opcodes.ASTORE, 4); 1295 1296 iVisited.getBodyNode().accept(this); 1297 1298 return null; 1299 } 1300 1301 public Instruction visitSClassNode(SClassNode iVisited) { 1302 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1303 } 1304 1305 public Instruction visitSelfNode(SelfNode iVisited) { 1306 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1307 } 1308 1309 public Instruction visitSplatNode(SplatNode iVisited) { 1310 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1311 } 1312 1313 public Instruction visitStrNode(StrNode iVisited) { 1314 lineNumber(iVisited); 1315 loadRuntime(); 1316 mv.visitLdcInsn(iVisited.getValue()); 1317 invokeRuby("newString", "(Ljava/lang/String;)Lorg/jruby/RubyString;"); 1318 1319 return null; 1320 } 1321 1322 public Instruction visitSuperNode(SuperNode iVisited) { 1323 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1324 } 1325 1326 public Instruction visitSValueNode(SValueNode iVisited) { 1327 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1328 } 1329 1330 public Instruction visitSymbolNode(SymbolNode iVisited) { 1331 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1332 } 1333 1334 public Instruction visitToAryNode(ToAryNode iVisited) { 1335 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1336 } 1337 1338 public Instruction visitTrueNode(TrueNode iVisited) { 1339 lineNumber(iVisited); 1340 loadRuntime(); 1341 invokeRuby("getTrue", "()Lorg/jruby/RubyBoolean;"); 1342 1343 return null; 1344 } 1345 1346 public Instruction visitUndefNode(UndefNode iVisited) { 1347 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1348 } 1349 1350 public Instruction visitUntilNode(UntilNode iVisited) { 1351 lineNumber(iVisited); 1352 1353 1355 loadRuntime(); 1357 invokeRuby("getNil", "()Lorg/jruby/runtime/builtin/IRubyObject;"); 1358 1359 if (iVisited.getBodyNode() != null) { 1360 Label l1 = new Label(); 1361 Label l2 = new Label(); 1362 1363 mv.visitLabel(l1); 1364 1365 iVisited.getConditionNode().accept(this); 1366 invokeIRubyObject("isTrue", "()Z"); 1367 mv.visitJumpInsn(Opcodes.IFNE, l2); 1369 1370 iVisited.getBodyNode().accept(this); 1371 mv.visitInsn(Opcodes.POP); 1373 1374 mv.visitJumpInsn(Opcodes.GOTO, l1); 1376 1377 mv.visitLabel(l2); 1378 } 1379 1380 return null; 1381 } 1382 1383 public Instruction visitVAliasNode(VAliasNode iVisited) { 1384 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1385 } 1386 1387 public Instruction visitVCallNode(VCallNode iVisited) { 1388 lineNumber(iVisited); 1389 loadSelf(); 1390 loadThreadContext(); 1391 1392 mv.visitLdcInsn(iVisited.getName()); 1393 1394 mv.visitFieldInsn(Opcodes.GETSTATIC, "org/jruby/runtime/builtin/IRubyObject", "NULL_ARRAY", "[Lorg/jruby/runtime/builtin/IRubyObject;"); 1395 mv.visitFieldInsn(Opcodes.GETSTATIC, "org/jruby/runtime/CallType", "FUNCTIONAL", "Lorg/jruby/runtime/CallType;"); 1396 1397 invokeIRubyObject("callMethod", "(Lorg/jruby/runtime/ThreadContext;Ljava/lang/String;[Lorg/jruby/runtime/builtin/IRubyObject;Lorg/jruby/runtime/CallType;)Lorg/jruby/runtime/builtin/IRubyObject;"); 1398 1399 return null; 1400 } 1401 1402 public Instruction visitWhenNode(WhenNode iVisited) { 1403 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1404 } 1405 1406 public Instruction visitWhileNode(WhileNode iVisited) { 1407 lineNumber(iVisited); 1408 1409 loadRuntime(); 1411 invokeRuby("getNil", "()Lorg/jruby/runtime/builtin/IRubyObject;"); 1412 1413 if (iVisited.getBodyNode() != null) { 1414 Label l1 = new Label(); 1415 Label l2 = new Label(); 1416 1417 mv.visitLabel(l1); 1418 1419 if (iVisited.evaluateAtStart()) { 1420 iVisited.getConditionNode().accept(this); 1421 invokeIRubyObject("isTrue", "()Z"); 1422 mv.visitJumpInsn(Opcodes.IFEQ, l2); 1424 } 1425 1426 iVisited.getBodyNode().accept(this); 1427 mv.visitInsn(Opcodes.POP); 1429 1430 if (!iVisited.evaluateAtStart()) { 1431 iVisited.getConditionNode().accept(this); 1432 invokeIRubyObject("isTrue", "()Z"); 1433 mv.visitJumpInsn(Opcodes.IFNE, l1); 1435 } else { 1436 mv.visitJumpInsn(Opcodes.GOTO, l1); 1438 } 1439 1440 mv.visitLabel(l2); 1441 } 1442 1443 return null; 1444 } 1445 1446 public Instruction visitXStrNode(XStrNode iVisited) { 1447 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1448 } 1449 1450 public Instruction visitYieldNode(YieldNode iVisited) { 1451 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1452 } 1453 1454 public Instruction visitZArrayNode(ZArrayNode iVisited) { 1455 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1456 } 1457 1458 public Instruction visitZSuperNode(ZSuperNode iVisited) { 1459 throw new NotCompilableException("Node not supported: " + iVisited.toString()); 1460 } 1461 1462 private void lineNumber(Node iVisited) { 1463 if (!EXPERIMENTAL_SOURCING) { 1464 return; 1465 } 1466 if (lastLine == (lastLine = iVisited.getPosition().getEndLine())) return; 1468 Label l = new Label(); 1469 mv.visitLabel(l); 1470 mv.visitLineNumber(iVisited.getPosition().getEndLine(), l); 1471 } 1472 1473 public Map getClassWriters() { 1474 return classWriters; 1475 } 1476 1477 private void setupArgs(Node node) { 1478 if (node == null) { 1479 mv.visitInsn(Opcodes.ICONST_0); 1480 mv.visitTypeInsn(Opcodes.ANEWARRAY, IRUBYOBJECT); 1481 } else if (node instanceof ArrayNode) { 1482 lineNumber(node); 1483 int count = ((ArrayNode)node).size(); 1484 mv.visitLdcInsn(new Integer (count)); 1485 mv.visitTypeInsn(Opcodes.ANEWARRAY, IRUBYOBJECT); 1486 1487 int i = 0; 1488 for (Iterator iter = ((ArrayNode) node).iterator(); iter.hasNext();) { 1489 final Node next = (Node) iter.next(); 1490 1491 mv.visitInsn(Opcodes.DUP); 1492 mv.visitLdcInsn(new Integer (i)); 1493 1494 if (next instanceof SplatNode) { 1496 } else { 1498 next.accept(this); 1499 } 1500 1501 mv.visitInsn(Opcodes.AASTORE); 1502 i++; 1503 } 1504 } 1505 } 1506 1507 private void loadThreadContext() { 1508 mv.visitVarInsn(Opcodes.ALOAD, 1); 1510 } 1511 1512 private void loadRuntime() { 1513 mv.visitVarInsn(Opcodes.ALOAD, 1); 1520 invokeThreadContext("getRuntime", "()Lorg/jruby/Ruby;"); 1521 } 1526 1527 private void loadSelf() { 1528 mv.visitVarInsn(Opcodes.ALOAD, 2); 1529 } 1530 1531 private void getCRefClass() { 1532 loadThreadContext(); 1533 invokeThreadContext("peekCRef", "()Lorg/jruby/util/collections/SinglyLinkedList;"); 1534 mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/jruby/util/collections/SinglyLinkedList", "getValue", "()Ljava/lang/Object;"); 1535 mv.visitTypeInsn(Opcodes.CHECKCAST, RUBYMODULE); 1536} 1537 private void getRubyClass() { 1538 loadThreadContext(); 1539 invokeThreadContext("getRubyClass", "()Lorg/jruby/RubyModule;"); 1540 } 1541} 1542 | Popular Tags |