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 */ 013package org.jikesrvm.compilers.opt.controlflow; 014 015import static org.jikesrvm.compilers.opt.driver.OptConstants.INSTRUMENTATION_BCI; 016import static org.jikesrvm.compilers.opt.ir.Operators.IR_PROLOGUE_opcode; 017import static org.jikesrvm.compilers.opt.ir.Operators.YIELDPOINT_BACKEDGE; 018import static org.jikesrvm.compilers.opt.ir.Operators.YIELDPOINT_EPILOGUE; 019import static org.jikesrvm.compilers.opt.ir.Operators.YIELDPOINT_PROLOGUE; 020 021import java.util.Enumeration; 022 023import org.jikesrvm.VM; 024import org.jikesrvm.compilers.opt.driver.CompilerPhase; 025import org.jikesrvm.compilers.opt.inlining.InlineSequence; 026import org.jikesrvm.compilers.opt.ir.BasicBlock; 027import org.jikesrvm.compilers.opt.ir.Empty; 028import org.jikesrvm.compilers.opt.ir.IR; 029import org.jikesrvm.compilers.opt.ir.Instruction; 030import 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 */ 040public 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.getInlineSequence()); 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.getInlineSequence()); 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 * @param n a loop node 098 */ 099 private void processLoopNest(LSTNode n) { 100 for (java.util.Enumeration<LSTNode> e = n.getChildren(); e.hasMoreElements();) { 101 processLoopNest(e.nextElement()); 102 } 103 Instruction dest = n.header.firstInstruction(); 104 if (dest.position.getMethod().isInterruptible()) { 105 prependYield(n.header, YIELDPOINT_BACKEDGE, dest.bcIndex, dest.position); 106 } 107 } 108 109 /** 110 * Add a YIELD instruction to the appropriate place for the basic 111 * block passed. 112 * 113 * @param bb the basic block 114 * @param yp the yieldpoint operator to insert 115 * @param bcIndex the bcIndex of the yieldpoint 116 * @param position the source position of the yieldpoint 117 */ 118 private void prependYield(BasicBlock bb, Operator yp, int bcIndex, InlineSequence position) { 119 Instruction insertionPoint = null; 120 121 if (bb.isEmpty()) { 122 insertionPoint = bb.lastInstruction(); 123 } else { 124 insertionPoint = bb.firstRealInstruction(); 125 } 126 127 if (yp == YIELDPOINT_PROLOGUE) { 128 if (VM.VerifyAssertions) { 129 VM._assert((insertionPoint != null) && (insertionPoint.getOpcode() == IR_PROLOGUE_opcode)); 130 } 131 // put it after the prologue 132 insertionPoint = insertionPoint.nextInstructionInCodeOrder(); 133 } else if (VM.UseEpilogueYieldPoints && yp == YIELDPOINT_EPILOGUE) { 134 // epilogues go before the return or athrow (at end of block) 135 insertionPoint = bb.lastRealInstruction(); 136 } 137 138 Instruction s = Empty.create(yp); 139 insertionPoint.insertBefore(s); 140 s.position = position; 141 s.bcIndex = bcIndex; 142 } 143} 144 145 146 147