001 /* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013 package org.jikesrvm.compilers.opt.controlflow; 014 015 import static org.jikesrvm.compilers.opt.driver.OptConstants.INSTRUMENTATION_BCI; 016 import static org.jikesrvm.compilers.opt.ir.Operators.IR_PROLOGUE_opcode; 017 import static org.jikesrvm.compilers.opt.ir.Operators.YIELDPOINT_BACKEDGE; 018 import static org.jikesrvm.compilers.opt.ir.Operators.YIELDPOINT_EPILOGUE; 019 import static org.jikesrvm.compilers.opt.ir.Operators.YIELDPOINT_PROLOGUE; 020 021 import java.util.Enumeration; 022 023 import org.jikesrvm.VM; 024 import org.jikesrvm.compilers.opt.driver.CompilerPhase; 025 import org.jikesrvm.compilers.opt.inlining.InlineSequence; 026 import org.jikesrvm.compilers.opt.ir.BasicBlock; 027 import org.jikesrvm.compilers.opt.ir.Empty; 028 import org.jikesrvm.compilers.opt.ir.IR; 029 import org.jikesrvm.compilers.opt.ir.Instruction; 030 import org.jikesrvm.compilers.opt.ir.Operator; 031 032 /** 033 * This class inserts yield points in 034 * <ul> 035 * <li>1) a method's prologue 036 * <li>2) loop headers 037 * <li>3) (optionally) method exits (epilogue, athrow) 038 * </ul> 039 */ 040 public class YieldPoints extends CompilerPhase { 041 042 /** 043 * Return the name of this phase 044 * @return "Yield Point Insertion" 045 */ 046 @Override 047 public final String getName() { 048 return "Yield Point Insertion"; 049 } 050 051 /** 052 * This phase contains no per-compilation instance fields. 053 */ 054 @Override 055 public final CompilerPhase newExecution(IR ir) { 056 return this; 057 } 058 059 /** 060 * Insert yield points in method prologues, loop heads, and method exits 061 * 062 */ 063 @Override 064 public final void perform(IR ir) { 065 if (!ir.method.isInterruptible()) { 066 return; // don't insert yieldpoints in Uninterruptible code. 067 } 068 069 // (1) Insert prologue yieldpoint unconditionally. 070 // As part of prologue/epilogue insertion we'll remove 071 // the yieldpoints in trivial methods that otherwise wouldn't need 072 // a stackframe. 073 prependYield(ir.cfg.entry(), YIELDPOINT_PROLOGUE, 0, ir.gc.inlineSequence); 074 075 // (2) If using epilogue yieldpoints scan basic blocks, looking for returns or throws 076 if (VM.UseEpilogueYieldPoints) { 077 for (Enumeration<BasicBlock> e = ir.getBasicBlocks(); e.hasMoreElements();) { 078 BasicBlock block = e.nextElement(); 079 if (block.hasReturn() || block.hasAthrowInst()) { 080 prependYield(block, YIELDPOINT_EPILOGUE, INSTRUMENTATION_BCI, ir.gc.inlineSequence); 081 } 082 } 083 } 084 085 // (3) Insert yieldpoints in loop heads based on the LST. 086 LSTGraph lst = ir.HIRInfo.loopStructureTree; 087 if (lst != null) { 088 for (java.util.Enumeration<LSTNode> e = lst.getRoot().getChildren(); e.hasMoreElements();) { 089 processLoopNest(e.nextElement()); 090 } 091 } 092 } 093 094 /** 095 * Process all loop heads in a loop nest by inserting a backedge yieldpoint in each of them. 096 */ 097 private void processLoopNest(LSTNode n) { 098 for (java.util.Enumeration<LSTNode> e = n.getChildren(); e.hasMoreElements();) { 099 processLoopNest(e.nextElement()); 100 } 101 Instruction dest = n.header.firstInstruction(); 102 if (dest.position.getMethod().isInterruptible()) { 103 prependYield(n.header, YIELDPOINT_BACKEDGE, dest.bcIndex, dest.position); 104 } 105 } 106 107 /** 108 * Add a YIELD instruction to the appropriate place for the basic 109 * block passed. 110 * 111 * @param bb the basic block 112 * @param yp the yieldpoint operator to insert 113 * @param bcIndex the bcIndex of the yieldpoint 114 * @param position the source position of the yieldpoint 115 */ 116 private void prependYield(BasicBlock bb, Operator yp, int bcIndex, InlineSequence position) { 117 Instruction insertionPoint = null; 118 119 if (bb.isEmpty()) { 120 insertionPoint = bb.lastInstruction(); 121 } else { 122 insertionPoint = bb.firstRealInstruction(); 123 } 124 125 if (yp == YIELDPOINT_PROLOGUE) { 126 if (VM.VerifyAssertions) { 127 VM._assert((insertionPoint != null) && (insertionPoint.getOpcode() == IR_PROLOGUE_opcode)); 128 } 129 // put it after the prologue 130 insertionPoint = insertionPoint.nextInstructionInCodeOrder(); 131 } else if (VM.UseEpilogueYieldPoints && yp == YIELDPOINT_EPILOGUE) { 132 // epilogues go before the return or athrow (at end of block) 133 insertionPoint = bb.lastRealInstruction(); 134 } 135 136 Instruction s = Empty.create(yp); 137 insertionPoint.insertBefore(s); 138 s.position = position; 139 s.bcIndex = bcIndex; 140 } 141 } 142 143 144 145