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.bc2ir; 014 015import org.jikesrvm.compilers.opt.inlining.InlineSequence; 016import org.jikesrvm.compilers.opt.ir.BasicBlock; 017import org.jikesrvm.compilers.opt.ir.ControlFlowGraph; 018import org.jikesrvm.compilers.opt.ir.operand.Operand; 019 020/** 021 * This class is used as a 'wrapper' to a basic block to hold 022 * information that is necessary only for IR generation. 023 */ 024class BasicBlockLE { 025 // Used by BBSet to maintain red/black tree of BBLE's during generation 026 BasicBlockLE parent, left, right; 027 028 /** Start bytecode of this BBLE */ 029 final int low; 030 031 /** Current end bytecode of this BBLE */ 032 int high; 033 034 /** Maximum possible bytecode of this BBLE (wrt exception ranges) */ 035 int max; 036 037 /** Basic block that this BBLE refers to. */ 038 BasicBlock block; 039 040 /** State of the stack at the start of this basic block. */ 041 OperandStack stackState; 042 043 /** State of the local variables at the start of this basic block. */ 044 Operand[] localState; 045 046 /** 047 * The desired fallthrough (next in code order) BBLE (may be {@code null}). 048 * NOTE: we may not always end up actually falling through 049 * (see BBSet.finalPass). 050 */ 051 BasicBlockLE fallThrough; 052 053 /** 054 * The exception handler BBLE's for this block ({@code null} if none) 055 */ 056 HandlerBlockLE[] handlers; 057 058 /** 059 * Encoding of random boolean state 060 */ 061 private byte flags; 062 private static final byte STACK_KNOWN = 0x01; 063 private static final byte LOCAL_KNOWN = 0x02; 064 private static final byte SELF_REGEN = 0x04; 065 private static final byte GENERATED = 0x08; 066 private static final byte COLOR = 0x10; //(Red = 0, Black = 1) 067 private static final byte IN_CODE_ORDER = 0x20; 068 069 final void setStackKnown() { 070 flags |= STACK_KNOWN; 071 } 072 073 final void clearStackKnown() { 074 flags &= ~STACK_KNOWN; 075 } 076 077 final boolean isStackKnown() { 078 return (flags & STACK_KNOWN) != 0; 079 } 080 081 final void setLocalKnown() { 082 flags |= LOCAL_KNOWN; 083 } 084 085 final void clearLocalKnown() { 086 flags &= ~LOCAL_KNOWN; 087 } 088 089 final boolean isLocalKnown() { 090 return (flags & LOCAL_KNOWN) != 0; 091 } 092 093 final void setSelfRegen() { 094 flags |= SELF_REGEN; 095 } 096 097 final void clearSelfRegen() { 098 flags &= ~SELF_REGEN; 099 } 100 101 final boolean isSelfRegen() { 102 return (flags & SELF_REGEN) != 0; 103 } 104 105 final void setGenerated() { 106 flags |= GENERATED; 107 } 108 109 final void clearGenerated() { 110 flags &= ~GENERATED; 111 } 112 113 final boolean isGenerated() { 114 return (flags & GENERATED) != 0; 115 } 116 117 final void setBlack() { 118 flags |= COLOR; 119 } 120 121 final boolean isBlack() { 122 return (flags & COLOR) != 0; 123 } 124 125 final void setRed() { 126 flags &= ~COLOR; 127 } 128 129 final boolean isRed() { 130 return (flags & COLOR) == 0; 131 } 132 133 final void setInCodeOrder() { 134 flags |= IN_CODE_ORDER; 135 } 136 137 final void clearInCodeOrder() { 138 flags &= ~IN_CODE_ORDER; 139 } 140 141 final boolean isInCodeOrder() { 142 return (flags & IN_CODE_ORDER) != 0; 143 } 144 145 final boolean isReadyToGenerate() { 146 // (isStackKnown() && isLocalKnown && !isGenerated) 147 byte READY_MASK = STACK_KNOWN | LOCAL_KNOWN | GENERATED; 148 byte READY_VAL = STACK_KNOWN | LOCAL_KNOWN; 149 return (flags & READY_MASK) == READY_VAL; 150 } 151 152 /** 153 * Save a shallow copy of the given local variable state into this. 154 * @param _localState local variable state to save 155 */ 156 final void copyIntoLocalState(Operand[] _localState) { 157 localState = new Operand[_localState.length]; 158 System.arraycopy(_localState, 0, localState, 0, _localState.length); 159 setLocalKnown(); 160 } 161 162 /** 163 * @return a shallow copy of the local state 164 */ 165 final Operand[] copyLocalState() { 166 Operand[] ls = new Operand[localState.length]; 167 System.arraycopy(localState, 0, ls, 0, localState.length); 168 return ls; 169 } 170 171 /** 172 * Adds an exception handler BBLE to the handlers array. 173 * <p> 174 * NOTE: this isn't incredibly efficient, but empirically the expected 175 * number of handlers per basic block is 0, with an observed 176 * maximum across 10,000+ methods of 3. 177 * Until this changes, we just don't care. 178 * 179 * @param handler the handler block to add 180 */ 181 final void addHandler(HandlerBlockLE handler) { 182 if (handlers == null) { 183 handlers = new HandlerBlockLE[1]; 184 handlers[0] = handler; 185 } else { 186 for (HandlerBlockLE handler1 : handlers) { 187 if (handler1 == handler) { 188 return; //already there (was in emap more than once) 189 } 190 } 191 int n = handlers.length; 192 HandlerBlockLE[] tmp = new HandlerBlockLE[n + 1]; 193 for (int i = 0; i < n; i++) { 194 tmp[i] = handlers[i]; 195 } 196 tmp[n] = handler; 197 handlers = tmp; 198 } 199 } 200 201 /** 202 * Create a new BBLE (and basic block) for the specified bytecode index. 203 * 204 * @param loc bytecode index 205 * @param position the inline sequence 206 * @param cfg ControlFlowGraph into which the block 207 * will eventually be inserted 208 */ 209 BasicBlockLE(int loc, InlineSequence position, ControlFlowGraph cfg) { 210 block = new BasicBlock(loc, position, cfg); 211 low = loc; 212 high = loc; 213 } 214 215 // Only for use by subclasses to avoid above constructor. 216 protected BasicBlockLE(int loc) { 217 low = loc; 218 } 219 220 /** 221 * Returns a string representation of this BBLE. 222 */ 223 @Override 224 public String toString() { 225 if (isGenerated()) { 226 return "(" + low + "," + high + "," + max + ")"; 227 } 228 if (isReadyToGenerate()) { 229 return "{" + low + "," + max + "}"; 230 } 231 return "[" + low + "," + max + "]"; 232 } 233 234 /** 235 * @return a string representation of state that determines if the BBLE 236 * is ready to be generated 237 */ 238 public String genState() { 239 return "(sk=" + isStackKnown() + ", lk=" + isLocalKnown() + ", gen=" + isGenerated() + ")"; 240 } 241}