1 28 package org.jruby.compiler.yarv; 29 30 import java.util.List ; 31 import java.util.ArrayList ; 32 import java.util.Iterator ; 33 import java.util.Map ; 34 import java.util.IdentityHashMap ; 35 36 import org.jruby.Ruby; 37 import org.jruby.runtime.builtin.IRubyObject; 38 import org.jruby.ast.AndNode; 39 import org.jruby.ast.ArgsNode; 40 import org.jruby.ast.ArgumentNode; 41 import org.jruby.ast.ArrayNode; 42 import org.jruby.ast.BlockNode; 43 import org.jruby.ast.CallNode; 44 import org.jruby.ast.ConstNode; 45 import org.jruby.ast.DefnNode; 46 import org.jruby.ast.NewlineNode; 47 import org.jruby.ast.NotNode; 48 import org.jruby.ast.FixnumNode; 49 import org.jruby.ast.FCallNode; 50 import org.jruby.ast.IfNode; 51 import org.jruby.ast.ListNode; 52 import org.jruby.ast.LocalAsgnNode; 53 import org.jruby.ast.LocalVarNode; 54 import org.jruby.ast.OrNode; 55 import org.jruby.ast.VCallNode; 56 import org.jruby.ast.IArgumentNode; 57 import org.jruby.ast.HashNode; 58 import org.jruby.ast.OptNNode; 59 import org.jruby.ast.Node; 60 import org.jruby.ast.NodeTypes; 61 import org.jruby.ast.RootNode; 62 import org.jruby.ast.StrNode; 63 import org.jruby.ast.UntilNode; 64 import org.jruby.ast.WhileNode; 65 import org.jruby.ast.executable.YARVInstructions; 66 import org.jruby.ast.executable.YARVMachine; 67 import org.jruby.ast.types.ILiteralNode; 68 import org.jruby.ast.types.INameNode; 69 import org.jruby.compiler.Compiler; 70 import org.jruby.compiler.NodeCompiler; 71 72 75 public class StandardYARVCompiler implements NodeCompiler { 76 private YARVMachine.InstructionSequence iseq; 77 private Ruby runtime; 78 private int last_line = -1; 79 80 private LinkAnchor current_iseq; 81 82 private String [] locals = new String [0]; 83 84 private static final int COMPILE_OK=1; 85 private static final int COMPILE_NG=0; 86 87 private static abstract class LinkElement { 88 public LinkElement next; 89 public LinkElement prev; 90 } 91 92 private static class LinkAnchor extends LinkElement { 93 LinkElement last; 94 } 95 96 private static class Label extends LinkElement { 97 int label_no; 98 int position; 99 int sc_state; 100 int set; 101 int sp; 102 } 103 104 private static class Insn extends LinkElement { 105 YARVMachine.Instruction i; 106 } 107 108 private static class EnsureRange { 109 Label begin; 110 Label end; 111 EnsureRange next; 112 } 113 114 private static void verify_list(String info, LinkAnchor anchor) { 115 int flag = 0; 116 LinkElement list = anchor.next; 117 LinkElement plist = anchor; 118 while(list != null) { 119 if(plist != list.prev) { 120 flag++; 121 } 122 plist = list; 123 list = list.next; 124 } 125 126 if(anchor.last != plist && anchor.last != null) { 127 flag |= 0x70000; 128 } 129 130 if(flag != 0) { 131 throw new RuntimeException ("list verify error: " + Integer.toString(flag, 16) + " (" + info + ")"); 132 } 133 } 134 135 private int label_no = 0; 136 private Label NEW_LABEL(int l) { 137 Label labelobj = new Label(); 138 labelobj.next = null; 139 labelobj.label_no = label_no++; 140 labelobj.sc_state = 0; 141 labelobj.sp = -1; 142 return labelobj; 143 } 144 145 private static void ADD_LABEL(LinkAnchor anchor, LinkElement elem) { 146 ADD_ELEM(anchor,elem); 147 } 148 149 private static void ADD_ELEM(LinkAnchor anchor, LinkElement elem) { 150 elem.prev = anchor.last; 151 anchor.last.next = elem; 152 anchor.last = elem; 153 verify_list("add", anchor); 154 } 155 156 private static void INSERT_ELEM_PREV(LinkElement elem1, LinkElement elem2) { 157 elem2.prev = elem1.prev; 158 elem2.next = elem1; 159 elem1.prev = elem2; 160 if(elem2.prev != null) { 161 elem2.prev.next = elem2; 162 } 163 } 164 165 private static void REPLACE_ELEM(LinkElement elem1, LinkElement elem2) { 166 elem2.prev = elem1.prev; 167 elem2.next = elem1.next; 168 if(elem1.prev != null) { 169 elem1.prev.next = elem2; 170 } 171 if(elem1.next != null) { 172 elem1.next.prev = elem2; 173 } 174 } 175 176 private static void REMOVE_ELEM(LinkElement elem) { 177 elem.prev.next = elem.next; 178 if(elem.next != null) { 179 elem.next.prev = elem.prev; 180 } 181 } 182 183 private static LinkElement FIRST_ELEMENT(LinkAnchor anchor) { 184 return anchor.next; 185 } 186 187 private static LinkElement POP_ELEMENT(LinkAnchor anchor) { 188 LinkElement elem = anchor.last; 189 anchor.last = anchor.last.prev; 190 anchor.last.next = null; 191 verify_list("pop", anchor); 192 return elem; 193 } 194 195 private static LinkElement SHIFT_ELEMENT(LinkAnchor anchor) { 196 LinkElement elem = anchor.next; 197 if(null != elem) { 198 anchor.next = elem.next; 199 } 200 return elem; 201 } 202 203 private static int LIST_SIZE(LinkAnchor anchor) { 204 LinkElement elem = anchor.next; 205 int size = 0; 206 while(elem != null) { 207 size++; 208 elem = elem.next; 209 } 210 return size; 211 } 212 213 private static boolean LIST_SIZE_ZERO(LinkAnchor anchor) { 214 return anchor.next == null; 215 } 216 217 private static void APPEND_LIST(LinkAnchor anc1, LinkAnchor anc2) { 218 if(anc2.next != null) { 219 anc1.last.next = anc2.next; 220 anc2.next.prev = anc1.last; 221 anc1.last = anc2.last; 222 } 223 verify_list("append", anc1); 224 } 225 226 private static void INSERT_LIST(LinkAnchor anc1, LinkAnchor anc2) { 227 if(anc2.next != null) { 228 LinkElement first = anc1.next; 229 anc1.next = anc2.next; 230 anc1.next.prev = anc1; 231 anc2.last.next = first; 232 if(first != null) { 233 first.prev = anc2.last; 234 } else { 235 anc1.last = anc2.last; 236 } 237 } 238 verify_list("append", anc1); 239 } 240 241 private static void ADD_SEQ(LinkAnchor seq1, LinkAnchor seq2) { 242 APPEND_LIST(seq1,seq2); 243 } 244 245 private int debug_compile(String msg, int v) { 246 debugs(msg); 247 return v; 248 } 249 250 private int COMPILE(LinkAnchor anchor, String desc, Node node) { 251 return debug_compile("== " + desc, iseq_compile_each(anchor, node, false)); 252 } 253 254 private int COMPILE(LinkAnchor anchor, String desc, Node node, boolean poped) { 255 return debug_compile("== " + desc, iseq_compile_each(anchor, node, poped)); 256 } 257 258 private int COMPILE_POPED(LinkAnchor anchor, String desc, Node node) { 259 return debug_compile("== " + desc, iseq_compile_each(anchor, node, true)); 260 } 261 262 private LinkAnchor DECL_ANCHOR() { 263 LinkAnchor l = new LinkAnchor(); 264 l.last = l; 265 return l; 266 } 267 268 public StandardYARVCompiler(Ruby runtime) { 269 this.runtime = runtime; 270 } 271 272 private void debugs(String s) { 273 System.err.println(s); 274 } 275 276 public void compile(Node node) { 277 iseq_compile(null,node); 278 } 279 280 public void compile(Node node, Compiler context) { 281 compile(node); 282 } 283 284 public void iseq_compile(IRubyObject self, Node narg) { 285 LinkAnchor list_anchor = DECL_ANCHOR(); 286 Node node = narg; 287 debugs("[compile step 1 (traverse each node)]"); 288 COMPILE(list_anchor, "top level node", node); 289 ADD_INSN(list_anchor, last_line, YARVInstructions.LEAVE); 290 current_iseq = list_anchor; 291 } 292 293 private int nd_line(Node node) { 294 if(node.getPosition() != null) { 295 return node.getPosition().getEndLine(); 296 } 297 return last_line; 298 } 299 300 private String nd_file(Node node) { 301 if(node.getPosition() != null) { 302 return node.getPosition().getFile(); 303 } 304 return null; 305 } 306 307 private int iseq_compile_each(LinkAnchor ret, Node node, boolean poped) { 308 if(node == null) { 309 if(!poped) { 310 debugs("NODE_NIL(implicit)"); 311 ADD_INSN(ret, 0, YARVInstructions.PUTNIL); 312 return COMPILE_OK; 313 } 314 return COMPILE_OK; 315 } 316 last_line = nd_line(node); 317 318 LinkAnchor recv = null; 319 LinkAnchor args = null; 320 321 compileLoop: while(true) { 322 switch(node.nodeId) { 323 case NodeTypes.BLOCKNODE: 324 List l = ((BlockNode)node).childNodes(); 325 int sz = l.size(); 326 for(int i=0;i<sz;i++) { 327 boolean p = !(i+1 == sz && !poped); 328 COMPILE(ret, "BLOCK body", (Node)l.get(i),p); 329 } 330 break compileLoop; 331 case NodeTypes.NEWLINENODE: 332 node = ((NewlineNode)node).getNextNode(); 333 continue compileLoop; 334 case NodeTypes.ROOTNODE: 335 locals = ((RootNode)node).getStaticScope().getAllNamesInScope(); 336 node = ((RootNode)node).getBodyNode(); 337 continue compileLoop; 338 case NodeTypes.DEFNNODE: 339 StandardYARVCompiler c = new StandardYARVCompiler(runtime); 340 c.compile(((DefnNode)node).getBodyNode()); 341 YARVMachine.InstructionSequence iseqval = c.getInstructionSequence(((DefnNode)node).getName(), nd_file(node), "method"); 342 List argNames = new ArrayList (); 343 for(Iterator iter = ((ArgsNode)((DefnNode)node).getArgsNode()).getArgs().iterator();iter.hasNext();) { 344 argNames.add(((ArgumentNode)iter.next()).getName()); 345 } 346 iseqval.args_argc = argNames.size(); 347 String [] l1 = iseqval.locals; 348 String [] l2 = new String [l1.length + argNames.size()]; 349 System.arraycopy(l1,0,l2,argNames.size(),l1.length); 350 for(int i=0;i<argNames.size();i++) { 351 l2[i] = (String )argNames.get(i); 352 } 353 iseqval.locals = l2; 354 ADD_INSN(ret, nd_line(node), YARVInstructions.PUTNIL); 355 ADD_INSN3(ret, nd_line(node), YARVInstructions.DEFINEMETHOD, ((DefnNode)node).getName(), iseqval, 0); 356 if(!poped) { 357 ADD_INSN(ret, nd_line(node), YARVInstructions.PUTNIL); 358 } 359 break compileLoop; 360 case NodeTypes.STRNODE: 361 if(!poped) { 362 ADD_INSN1(ret, nd_line(node), YARVInstructions.PUTSTRING, ((StrNode)node).getValue().toString()); 363 } 364 break compileLoop; 365 case NodeTypes.CONSTNODE: 366 ADD_INSN(ret, nd_line(node), YARVInstructions.PUTNIL); 368 ADD_INSN1(ret, nd_line(node), YARVInstructions.GETCONSTANT, ((ConstNode)node).getName()); 369 if(poped) { 370 ADD_INSN(ret, nd_line(node), YARVInstructions.POP); 371 } 372 break compileLoop; 373 case NodeTypes.LOCALASGNNODE: 374 int idx = ((LocalAsgnNode)node).getIndex()-2; 375 debugs("lvar: " + idx); 376 COMPILE(ret, "lvalue", ((LocalAsgnNode)node).getValueNode()); 377 if(!poped) { 378 ADD_INSN(ret, nd_line(node), YARVInstructions.DUP); 379 } 380 ADD_INSN1(ret, nd_line(node), YARVInstructions.SETLOCAL, idx); 381 break compileLoop; 382 case NodeTypes.LOCALVARNODE: 383 if(!poped) { 384 int idx2 = ((LocalVarNode)node).getIndex()-2; 385 debugs("idx: "+idx2); 386 ADD_INSN1(ret, nd_line(node), YARVInstructions.GETLOCAL, idx2); 387 } 388 break compileLoop; 389 case NodeTypes.IFNODE: { 390 LinkAnchor cond_seq = DECL_ANCHOR(); 391 LinkAnchor then_seq = DECL_ANCHOR(); 392 LinkAnchor else_seq = DECL_ANCHOR(); 393 394 Label then_label = NEW_LABEL(nd_line(node)); 395 Label else_label = NEW_LABEL(nd_line(node)); 396 Label end_label = NEW_LABEL(nd_line(node)); 397 398 compile_branch_condition(cond_seq, ((IfNode)node).getCondition(), then_label, else_label); 399 400 COMPILE(then_seq, "then", ((IfNode)node).getThenBody(), poped); 401 COMPILE(else_seq, "else", ((IfNode)node).getElseBody(), poped); 402 403 ADD_SEQ(ret, cond_seq); 404 405 ADD_LABEL(ret, then_label); 406 ADD_SEQ(ret, then_seq); 407 408 ADD_INSNL(ret, nd_line(node), YARVInstructions.JUMP, end_label); 409 410 ADD_LABEL(ret, else_label); 411 ADD_SEQ(ret, else_seq); 412 413 ADD_LABEL(ret, end_label); 414 break compileLoop; 415 } 416 case NodeTypes.CALLNODE: 417 case NodeTypes.FCALLNODE: 418 case NodeTypes.VCALLNODE: 419 recv = DECL_ANCHOR(); 420 args = DECL_ANCHOR(); 421 if(node instanceof CallNode) { 422 COMPILE(recv, "recv", ((CallNode)node).getReceiverNode()); 423 } else { 424 ADD_CALL_RECEIVER(recv, nd_line(node)); 425 } 426 int argc = 0; 427 int flags = 0; 428 if(!(node instanceof VCallNode)) { 429 int[] argc_flags = setup_arg(args, (IArgumentNode)node); 430 argc = argc_flags[0]; 431 flags = argc_flags[1]; 432 } else { 433 argc = 0; 434 } 435 436 ADD_SEQ(ret, recv); 437 ADD_SEQ(ret, args); 438 439 switch(node.nodeId) { 440 case NodeTypes.VCALLNODE: 441 flags |= YARVInstructions.VCALL_FLAG; 442 443 case NodeTypes.FCALLNODE: 444 flags |= YARVInstructions.FCALL_FLAG; 445 } 446 447 ADD_SEND_R(ret, nd_line(node), ((INameNode)node).getName(), argc, null, flags); 448 if(poped) { 449 ADD_INSN(ret, nd_line(node), YARVInstructions.POP); 450 } 451 break compileLoop; 452 case NodeTypes.ARRAYNODE: 453 compile_array(ret, node, true); 454 if(poped) { 455 ADD_INSN(ret, nd_line(node), YARVInstructions.POP); 456 } 457 break compileLoop; 458 case NodeTypes.ZARRAYNODE: 459 if(!poped) { 460 ADD_INSN1(ret, nd_line(node), YARVInstructions.NEWARRAY, 0); 461 } 462 break compileLoop; 463 case NodeTypes.HASHNODE: 464 LinkAnchor list = DECL_ANCHOR(); 465 long size = 0; 466 Node lnode = ((HashNode)node).getListNode(); 467 if(lnode.childNodes().size()>0) { 468 compile_array(list, lnode, false); 469 size = ((Insn)POP_ELEMENT(list)).i.l_op0; 470 ADD_SEQ(ret, list); 471 } 472 473 ADD_INSN1(ret, nd_line(node), YARVInstructions.NEWHASH, size); 474 475 if(poped) { 476 ADD_INSN(ret, nd_line(node), YARVInstructions.POP); 477 } 478 break compileLoop; 479 case NodeTypes.FIXNUMNODE: 480 FixnumNode iVisited = (FixnumNode) node; 481 if(!poped) { 482 ADD_INSN1(ret, nd_line(node), YARVInstructions.PUTOBJECT, iVisited.getFixnum(runtime)); 483 } 484 break compileLoop; 485 case NodeTypes.OPTNNODE: 486 case NodeTypes.WHILENODE: 487 case NodeTypes.UNTILNODE:{ 488 Label next_label = NEW_LABEL(nd_line(node)); 489 Label redo_label = NEW_LABEL(nd_line(node)); 490 Label break_label = NEW_LABEL(nd_line(node)); 491 Label end_label = NEW_LABEL(nd_line(node)); 492 493 if(node instanceof OptNNode) { 494 ADD_INSNL(ret, nd_line(node), YARVInstructions.JUMP, next_label); 495 } 496 497 ADD_LABEL(ret, redo_label); 498 499 Node body = null; 500 if(node instanceof WhileNode) { 501 body = ((WhileNode)node).getBodyNode(); 502 } else if(node instanceof UntilNode) { 503 body = ((UntilNode)node).getBodyNode(); 504 } else if(node instanceof OptNNode) { 505 body = ((OptNNode)node).getBodyNode(); 506 } 507 COMPILE_POPED(ret, "while body", body); 508 ADD_LABEL(ret, next_label); 509 510 if(node instanceof WhileNode) { 511 compile_branch_condition(ret, ((WhileNode)node).getConditionNode(), redo_label, end_label); 512 } else if(node instanceof UntilNode) { 513 514 compile_branch_condition(ret, ((UntilNode)node).getConditionNode(),end_label, redo_label); 515 } else { 516 ADD_CALL_RECEIVER(ret, nd_line(node)); 517 ADD_INSNL(ret, nd_line(node), YARVInstructions.BRANCHIF, redo_label) ; 519 520 } 521 522 ADD_LABEL(ret, end_label); 523 ADD_INSN(ret, nd_line(node), YARVInstructions.PUTNIL); 524 ADD_LABEL(ret, break_label); 525 if (poped) { 526 ADD_INSN(ret, nd_line(node), YARVInstructions.POP); 527 } 528 break compileLoop; 529 } 530 531 default: 532 debugs(" ... doesn't handle node: " + node); 533 break compileLoop; 534 } 535 } 536 537 return COMPILE_OK; 538 } 539 540 private int compile_branch_condition(LinkAnchor ret, Node cond, Label then_label, Label else_label) { 541 switch(cond.nodeId) { 542 case NodeTypes.NOTNODE: 543 compile_branch_condition(ret, ((NotNode)cond).getConditionNode(), else_label, then_label); 544 break; 545 case NodeTypes.ANDNODE: { 546 Label label = NEW_LABEL(nd_line(cond)); 547 compile_branch_condition(ret, ((AndNode)cond).getFirstNode(), label, else_label); 548 ADD_LABEL(ret, label); 549 compile_branch_condition(ret, ((AndNode)cond).getSecondNode(), then_label, else_label); 550 break; 551 } 552 case NodeTypes.ORNODE: { 553 Label label = NEW_LABEL(nd_line(cond)); 554 compile_branch_condition(ret, ((OrNode)cond).getFirstNode(), then_label, label); 555 ADD_LABEL(ret, label); 556 compile_branch_condition(ret, ((OrNode)cond).getSecondNode(), then_label, else_label); 557 break; 558 } 559 case NodeTypes.TRUENODE: 560 case NodeTypes.STRNODE: 561 ADD_INSNL(ret, nd_line(cond), YARVInstructions.JUMP, then_label); 562 break; 563 case NodeTypes.FALSENODE: 564 case NodeTypes.NILNODE: 565 ADD_INSNL(ret, nd_line(cond), YARVInstructions.JUMP, else_label); 566 break; 567 default: 568 COMPILE(ret, "branch condition", cond); 569 ADD_INSNL(ret, nd_line(cond), YARVInstructions.BRANCHUNLESS, else_label); 570 ADD_INSNL(ret, nd_line(cond), YARVInstructions.JUMP, then_label); 571 break; 572 } 573 574 return COMPILE_OK; 575 } 576 577 private int compile_array(LinkAnchor ret, Node node_root, boolean opt_p) { 578 Node node = node_root; 579 int len = ((ArrayNode)node).size(); 580 int line = nd_line(node); 581 int i =0; 582 LinkAnchor anchor = DECL_ANCHOR(); 583 List c = node.childNodes(); 584 for(Iterator iter = c.iterator(); iter.hasNext();) { 585 node = (Node)iter.next(); 586 if(opt_p && !(node instanceof ILiteralNode)) { 587 opt_p = false; 588 } 589 COMPILE(anchor, "array element", node); 590 } 591 592 if(opt_p) { 593 List l = new ArrayList (); 594 for(Iterator iter = c.iterator(); iter.hasNext();) { 595 node = (Node)iter.next(); 596 switch(node.nodeId) { 597 case NodeTypes.FIXNUMNODE: 598 l.add(((FixnumNode)node).getFixnum(runtime)); 599 break; 600 default: 601 debugs(" ... doesn't handle array literal node: " + node); 602 break; 603 } 604 } 605 ADD_INSN1(ret, nd_line(node_root), YARVInstructions.DUPARRAY, runtime.newArray(l)); 606 } else { 607 ADD_INSN1(anchor, line, YARVInstructions.NEWARRAY, len); 608 APPEND_LIST(ret, anchor); 609 } 610 611 return len; 612 } 613 614 private int[] setup_arg(LinkAnchor args, IArgumentNode node) { 615 int[] n = new int[] {0,0}; 616 Node argn = node.getArgsNode(); 617 LinkAnchor arg_block = DECL_ANCHOR(); 618 LinkAnchor args_push = DECL_ANCHOR(); 619 620 if(argn != null) { 621 switch(argn.nodeId) { 622 case NodeTypes.SPLATNODE: 623 break; 624 case NodeTypes.ARGSCATNODE: 625 break; 626 case NodeTypes.ARGSPUSHNODE: 627 break; 628 default: 629 n[0] = compile_array(args,argn,false); 630 POP_ELEMENT(args); 631 break; 632 } 633 } 634 635 if (!LIST_SIZE_ZERO(args_push)) { 636 ADD_SEQ(args, args_push); 637 } 638 639 return n; 640 } 641 642 private Insn new_insn(YARVMachine.Instruction i) { 643 Insn n = new Insn(); 644 n.i = i; 645 n.next = null; 646 return n; 647 } 648 649 private void ADD_CALL_RECEIVER(LinkAnchor seq, int line) { 650 ADD_INSN(seq, line, YARVInstructions.PUTNIL); 651 } 652 653 private void ADD_INSN(LinkAnchor seq, int line, int insn) { 654 YARVMachine.Instruction i = new YARVMachine.Instruction(insn); 655 i.line_no = line; 656 debugs("ADD_INSN(" + line + ", " + YARVInstructions.name(insn) + ")"); 657 ADD_ELEM(seq, new_insn(i)); 658 } 659 660 private void ADD_SEND_R(LinkAnchor seq, int line, String name, int argc, Object block, int flags) { 661 YARVMachine.Instruction i = new YARVMachine.Instruction(YARVInstructions.SEND); 662 i.line_no = line; 663 i.s_op0 = name; 664 i.i_op1 = argc; 665 i.i_op3 = flags; 666 debugs("ADD_SEND_R(" + line + ", " + YARVInstructions.name(YARVInstructions.SEND) + ", " + name + ", " + argc + ", " + flags + ")"); 667 ADD_ELEM(seq, new_insn(i)); 668 } 669 670 private void ADD_INSN1(LinkAnchor seq, int line, int insn, IRubyObject obj) { 671 YARVMachine.Instruction i = new YARVMachine.Instruction(insn); 672 i.line_no = line; 673 i.o_op0 = obj; 674 debugs("ADD_INSN1(" + line + ", " + YARVInstructions.name(insn) + ", " + obj + ")"); 675 ADD_ELEM(seq, new_insn(i)); 676 } 677 678 private void ADD_INSN1(LinkAnchor seq, int line, int insn, long op) { 679 YARVMachine.Instruction i = new YARVMachine.Instruction(insn); 680 i.line_no = line; 681 i.l_op0 = op; 682 debugs("ADD_INSN1(" + line + ", " + YARVInstructions.name(insn) + ", " + op + ")"); 683 ADD_ELEM(seq, new_insn(i)); 684 } 685 686 private void ADD_INSNL(LinkAnchor seq, int line, int insn, Label l) { 687 YARVMachine.Instruction i = new YARVMachine.Instruction(insn); 688 i.line_no = line; 689 i._tmp = l; 690 debugs("ADD_INSNL(" + line + ", " + YARVInstructions.name(insn) + ", " + l + ")"); 691 ADD_ELEM(seq, new_insn(i)); 692 } 693 694 private void ADD_INSN1(LinkAnchor seq, int line, int insn, String obj) { 695 YARVMachine.Instruction i = new YARVMachine.Instruction(insn); 696 i.line_no = line; 697 i.s_op0 = obj; 698 debugs("ADD_INSN1(" + line + ", " + YARVInstructions.name(insn) + ", " + obj + ")"); 699 ADD_ELEM(seq, new_insn(i)); 700 } 701 702 private void ADD_INSN3(LinkAnchor seq, int line, int insn, String name, YARVMachine.InstructionSequence iseq, long n) { 703 YARVMachine.Instruction i = new YARVMachine.Instruction(insn); 704 i.line_no = line; 705 i.s_op0 = name; 706 i.iseq_op = iseq; 707 i.l_op0 = n; 708 debugs("ADD_INSN3(" + line + ", " + YARVInstructions.name(insn) + ", " + name + ", " + iseq + ", " + n + ")"); 709 ADD_ELEM(seq, new_insn(i)); 710 } 711 712 public YARVMachine.InstructionSequence getInstructionSequence(String name, String filename, String level) { 713 iseq = new YARVMachine.InstructionSequence(runtime, name, filename, level); 714 List l = new ArrayList (); 715 LinkElement elm = current_iseq; 716 Map jumps = new IdentityHashMap (); 717 Map labels = new IdentityHashMap (); 718 int real=0; 719 while(elm != null) { 720 if(elm instanceof Insn) { 721 Insn i = (Insn)elm; 722 if(isJump(i.i.bytecode)) { 723 jumps.put(i, i.i._tmp); 724 } 725 l.add(i.i); 726 real++; 727 } else if(elm instanceof Label) { 728 labels.put(elm, new Integer (real+1)); 729 } 730 elm = elm.next; 731 } 732 for(Iterator iter = jumps.keySet().iterator();iter.hasNext();) { 733 Insn k = (Insn)iter.next(); 734 k.i.l_op0 = ((Integer )labels.get(jumps.get(k))).intValue() - 1; 735 k.i._tmp = null; 736 } 737 738 debugs("instructions: " + l); 739 iseq.body = (YARVMachine.Instruction[])l.toArray(new YARVMachine.Instruction[l.size()]); 740 iseq.locals = locals; 741 return iseq; 742 } 743 744 private boolean isJump(int i) { 745 return i == YARVInstructions.JUMP || i == YARVInstructions.BRANCHIF || i == YARVInstructions.BRANCHUNLESS || 746 i == YARVInstructions.GETINLINECACHE || i == YARVInstructions.SETINLINECACHE; 747 } 748 } | Popular Tags |