KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jruby > compiler > yarv > StandardYARVCompiler


1 /***** BEGIN LICENSE BLOCK *****
2  * Version: CPL 1.0/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Common Public
5  * License Version 1.0 (the "License"); you may not use this file
6  * except in compliance with the License. You may obtain a copy of
7  * the License at http://www.eclipse.org/legal/cpl-v10.html
8  *
9  * Software distributed under the License is distributed on an "AS
10  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11  * implied. See the License for the specific language governing
12  * rights and limitations under the License.
13  *
14  * Copyright (C) 2007 Ola Bini <ola@ologix.com>
15  *
16  * Alternatively, the contents of this file may be used under the terms of
17  * either of the GNU General Public License Version 2 or later (the "GPL"),
18  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
19  * in which case the provisions of the GPL or the LGPL are applicable instead
20  * of those above. If you wish to allow use of your version of this file only
21  * under the terms of either the GPL or the LGPL, and not to allow others to
22  * use your version of this file under the terms of the CPL, indicate your
23  * decision by deleting the provisions above and replace them with the notice
24  * and other provisions required by the GPL or the LGPL. If you do not delete
25  * the provisions above, a recipient may use your version of this file under
26  * the terms of any one of the CPL, the GPL or the LGPL.
27  ***** END LICENSE BLOCK *****/

28 package org.jruby.compiler.yarv;
29
30 import java.util.List JavaDoc;
31 import java.util.ArrayList JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.IdentityHashMap JavaDoc;
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 /**
73  * @author <a HREF="mailto:ola.bini@ki.se">Ola Bini</a>
74  */

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 JavaDoc[] locals = new String JavaDoc[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 JavaDoc 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 JavaDoc("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 JavaDoc msg, int v) {
246         debugs(msg);
247         return v;
248     }
249
250     private int COMPILE(LinkAnchor anchor, String JavaDoc desc, Node node) {
251         return debug_compile("== " + desc, iseq_compile_each(anchor, node, false));
252     }
253
254     private int COMPILE(LinkAnchor anchor, String JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc argNames = new ArrayList JavaDoc();
343                 for(Iterator JavaDoc 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 JavaDoc[] l1 = iseqval.locals;
348                 String JavaDoc[] l2 = new String JavaDoc[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 JavaDoc)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                 // Check for inline const cache here
367
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                     /* VCALL is funcall, so fall through */
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)); /* next */
489                 Label redo_label = NEW_LABEL(nd_line(node)); /* redo */
490                 Label break_label = NEW_LABEL(nd_line(node)); /* break */
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); /* next */
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                     /* untile */
514                     compile_branch_condition(ret, ((UntilNode)node).getConditionNode(),end_label, redo_label);
515                 } else {
516                     ADD_CALL_RECEIVER(ret, nd_line(node));
517                     //TODO: ADD_CALL(ret, nd_line(node), ID2SYM(idGets), INT2FIX(0));
518
ADD_INSNL(ret, nd_line(node), YARVInstructions.BRANCHIF, redo_label) ;
519                     /* opt_n */
520                 }
521
522                 ADD_LABEL(ret, end_label);
523                 ADD_INSN(ret, nd_line(node), YARVInstructions.PUTNIL);
524                 ADD_LABEL(ret, break_label); /* braek */
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 JavaDoc c = node.childNodes();
584         for(Iterator JavaDoc 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 JavaDoc l = new ArrayList JavaDoc();
594             for(Iterator JavaDoc 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 JavaDoc name, int argc, Object JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc name, String JavaDoc filename, String JavaDoc level) {
713         iseq = new YARVMachine.InstructionSequence(runtime, name, filename, level);
714         List JavaDoc l = new ArrayList JavaDoc();
715         LinkElement elm = current_iseq;
716         Map JavaDoc jumps = new IdentityHashMap JavaDoc();
717         Map JavaDoc labels = new IdentityHashMap JavaDoc();
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 JavaDoc(real+1));
729             }
730             elm = elm.next;
731         }
732         for(Iterator JavaDoc iter = jumps.keySet().iterator();iter.hasNext();) {
733             Insn k = (Insn)iter.next();
734             k.i.l_op0 = ((Integer JavaDoc)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 }// StandardYARVCompiler
749
Popular Tags