PageRenderTime 36ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/src/org/jruby/compiler/ir/representations/BasicBlock.java

https://github.com/rkh/jruby
Java | 191 lines | 153 code | 30 blank | 8 comment | 36 complexity | e95fedd2d512f483e56287cf8ecbbdac MD5 | raw file
  1. package org.jruby.compiler.ir.representations;
  2. import org.jruby.compiler.ir.operands.Array;
  3. import org.jruby.compiler.ir.operands.Label;
  4. import org.jruby.compiler.ir.operands.Variable;
  5. import org.jruby.compiler.ir.operands.Operand;
  6. import org.jruby.compiler.ir.instructions.Instr;
  7. import org.jruby.compiler.ir.instructions.CopyInstr;
  8. import org.jruby.compiler.ir.instructions.ClosureReturnInstr;
  9. import org.jruby.compiler.ir.instructions.NopInstr;
  10. import org.jruby.compiler.ir.instructions.ReceiveClosureArgInstr;
  11. import org.jruby.compiler.ir.instructions.ReceiveClosureInstr;
  12. import org.jruby.compiler.ir.instructions.ReceiveSelfInstruction;
  13. import org.jruby.compiler.ir.instructions.YieldInstr;
  14. import java.util.List;
  15. import java.util.ArrayList;
  16. import java.util.ListIterator;
  17. public class BasicBlock {
  18. int _id; // Basic Block id
  19. CFG _cfg; // CFG that this basic block belongs to
  20. Label _label; // All basic blocks have a starting label
  21. List<Instr> _instrs; // List of non-label instructions
  22. boolean _isLive;
  23. public BasicBlock(CFG c, Label l) {
  24. _instrs = new ArrayList<Instr>();
  25. _label = l;
  26. _isLive = true;
  27. _cfg = c;
  28. _id = c.getNextBBID();
  29. }
  30. public void updateCFG(CFG c) {
  31. _cfg = c;
  32. _id = c.getNextBBID();
  33. }
  34. public int getID() {
  35. return _id;
  36. }
  37. public Label getLabel() {
  38. return _label;
  39. }
  40. public void addInstr(Instr i) {
  41. _instrs.add(i);
  42. }
  43. public void insertInstr(Instr i) {
  44. _instrs.add(0, i);
  45. }
  46. public List<Instr> getInstrs() {
  47. return _instrs;
  48. }
  49. private Instr[] _instrsArray = null;
  50. public Instr[] getInstrsArray() {
  51. if (_instrsArray == null) {
  52. _instrsArray = _instrs.toArray(new Instr[_instrs.size()]);
  53. }
  54. return _instrsArray;
  55. }
  56. public Instr getLastInstr() {
  57. int n = _instrs.size();
  58. return (n == 0) ? null : _instrs.get(n-1);
  59. }
  60. public boolean removeInstr(Instr i) {
  61. if (i == null)
  62. return false;
  63. else
  64. return _instrs.remove(i);
  65. }
  66. public boolean isEmpty() {
  67. return _instrs.isEmpty();
  68. }
  69. public BasicBlock splitAtInstruction(Instr splitPoint, Label newLabel, boolean includeSplitPointInstr) {
  70. BasicBlock newBB = new BasicBlock(_cfg, newLabel);
  71. int idx = 0;
  72. int numInstrs = _instrs.size();
  73. boolean found = false;
  74. for (Instr i: _instrs) {
  75. if (i == splitPoint)
  76. found = true;
  77. // Move instructions from split point into the new bb
  78. if (found) {
  79. if (includeSplitPointInstr || i != splitPoint)
  80. newBB.addInstr(i);
  81. }
  82. else {
  83. idx++;
  84. }
  85. }
  86. // Remove all instructions from current bb that were moved over.
  87. for (int j = 0; j < numInstrs-idx; j++)
  88. _instrs.remove(idx);
  89. return newBB;
  90. }
  91. public void swallowBB(BasicBlock foodBB) {
  92. this._instrs.addAll(foodBB._instrs);
  93. }
  94. public BasicBlock cloneForInlining(InlinerInfo ii) {
  95. BasicBlock clonedBB = ii.getOrCreateRenamedBB(this);
  96. for (Instr i: getInstrs()) {
  97. Instr clonedInstr = i.cloneForInlining(ii);
  98. if (clonedInstr != null) {
  99. clonedBB.addInstr(clonedInstr);
  100. if (clonedInstr instanceof YieldInstr) ii.recordYieldSite(clonedBB, (YieldInstr)clonedInstr);
  101. }
  102. }
  103. return clonedBB;
  104. }
  105. // SSS FIXME: Verify correctness; also deal with YieldInstr.wrapIntoArray flag
  106. public void processClosureArgAndReturnInstrs(InlinerInfo ii, YieldInstr yi) {
  107. Variable yieldResult = ii.getRenamedVariable(yi.result);
  108. Operand[] yieldArgs = yi.getNonBlockOperands();
  109. for (ListIterator<Instr> it = ((ArrayList<Instr>)_instrs).listIterator(); it.hasNext(); ) {
  110. Instr i = it.next();
  111. if (i instanceof ClosureReturnInstr) {
  112. // Replace the closure return receive with a simple copy
  113. it.set(new CopyInstr(yieldResult, ((ClosureReturnInstr)i).getArg()));
  114. }
  115. else if (i instanceof ReceiveSelfInstruction) {
  116. ReceiveSelfInstruction rsi = (ReceiveSelfInstruction)i;
  117. // SSS FIXME: It is not always the case that the call receiver is also the %self within
  118. // a block Ex: ... r.foo(args) { ... blah .. }. i.e. there are scenarios where %self
  119. // within the block is not identical to 'r'. Handle this!
  120. if (!rsi.result.equals(ii.getCallReceiver())) it.set(new CopyInstr(rsi.result, ii.getCallReceiver()));
  121. else it.set(NopInstr.NOP);
  122. }
  123. else if (i instanceof ReceiveClosureInstr) {
  124. ReceiveClosureInstr rci = (ReceiveClosureInstr)i;
  125. if (!rci.result.equals(ii.getCallClosure())) it.set(new CopyInstr(rci.result, ii.getCallClosure()));
  126. else it.set(NopInstr.NOP);
  127. }
  128. else if (i instanceof ReceiveClosureArgInstr) {
  129. Operand closureArg;
  130. ReceiveClosureArgInstr rcai = (ReceiveClosureArgInstr)i;
  131. int argIndex = rcai.argIndex;
  132. boolean restOfArgs = rcai.isRestOfArgArray();
  133. if (argIndex < yieldArgs.length) {
  134. closureArg = yieldArgs[argIndex].cloneForInlining(ii);
  135. }
  136. else if (argIndex >= yieldArgs.length) {
  137. closureArg = new Array();
  138. }
  139. else {
  140. Operand[] tmp = new Operand[yieldArgs.length - argIndex];
  141. for (int j = argIndex; j < yieldArgs.length; j++)
  142. tmp[j-argIndex] = yieldArgs[j].cloneForInlining(ii);
  143. closureArg = new Array(tmp);
  144. }
  145. // Replace the arg receive with a simple copy
  146. it.set(new CopyInstr(rcai.result, closureArg));
  147. }
  148. }
  149. }
  150. @Override
  151. public String toString() {
  152. return "BB [" + _id + ":" + _label + "]";
  153. }
  154. public String toStringInstrs() {
  155. StringBuilder buf = new StringBuilder(toString() + "\n");
  156. for (Instr instr : getInstrs()) {
  157. buf.append('\t').append(instr).append('\n');
  158. }
  159. return buf.toString();
  160. }
  161. }