59 import static org.graalvm.compiler.bytecode.Bytecodes.ILOAD_2; 60 import static org.graalvm.compiler.bytecode.Bytecodes.ILOAD_3; 61 import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE; 62 import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE_0; 63 import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE_1; 64 import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE_2; 65 import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE_3; 66 import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD; 67 import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD_0; 68 import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD_1; 69 import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD_2; 70 import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD_3; 71 import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE; 72 import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_0; 73 import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_1; 74 import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_2; 75 import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_3; 76 import static org.graalvm.compiler.bytecode.Bytecodes.RET; 77 78 import org.graalvm.compiler.bytecode.BytecodeStream; 79 import org.graalvm.compiler.debug.Debug; 80 import org.graalvm.compiler.java.BciBlockMapping.BciBlock; 81 82 /** 83 * Encapsulates the liveness calculation, so that subclasses for locals ≤ 64 and locals > 64 84 * can be implemented. 85 */ 86 public abstract class LocalLiveness { 87 protected final BciBlock[] blocks; 88 89 public static LocalLiveness compute(BytecodeStream stream, BciBlock[] blocks, int maxLocals, int loopCount) { 90 LocalLiveness liveness = maxLocals <= 64 ? new SmallLocalLiveness(blocks, maxLocals, loopCount) : new LargeLocalLiveness(blocks, maxLocals, loopCount); 91 liveness.computeLiveness(stream); 92 return liveness; 93 } 94 95 protected LocalLiveness(BciBlock[] blocks) { 96 this.blocks = blocks; 97 } 98 99 void computeLiveness(BytecodeStream stream) { 100 for (BciBlock block : blocks) { 101 computeLocalLiveness(stream, block); 102 } 103 104 boolean changed; 105 int iteration = 0; 106 do { 107 assert traceIteration(iteration); 108 changed = false; 109 for (int i = blocks.length - 1; i >= 0; i--) { 110 BciBlock block = blocks[i]; 111 int blockID = block.getId(); 112 assert traceStart(block, blockID); 113 114 boolean blockChanged = (iteration == 0); 115 if (block.getSuccessorCount() > 0) { 116 int oldCardinality = liveOutCardinality(blockID); 117 for (BciBlock sux : block.getSuccessors()) { 118 assert traceSuccessor(sux); 119 propagateLiveness(blockID, sux.getId()); 120 } 121 blockChanged |= (oldCardinality != liveOutCardinality(blockID)); 122 } 123 124 if (blockChanged) { 125 updateLiveness(blockID); 126 assert traceEnd(block, blockID); 127 } 128 changed |= blockChanged; 129 } 130 iteration++; 131 } while (changed); 132 } 133 134 private static boolean traceIteration(int iteration) { 135 Debug.log("Iteration %d", iteration); 136 return true; 137 } 138 139 private boolean traceEnd(BciBlock block, int blockID) { 140 if (Debug.isLogEnabled()) { 141 Debug.logv(" end B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.getId(), block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), debugLiveGen(blockID), 142 debugLiveKill(blockID)); 143 } 144 return true; 145 } 146 147 private boolean traceSuccessor(BciBlock sux) { 148 if (Debug.isLogEnabled()) { 149 Debug.log(" Successor B%d: %s", sux.getId(), debugLiveIn(sux.getId())); 150 } 151 return true; 152 } 153 154 private boolean traceStart(BciBlock block, int blockID) { 155 if (Debug.isLogEnabled()) { 156 Debug.logv(" start B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.getId(), block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), debugLiveGen(blockID), 157 debugLiveKill(blockID)); 158 } 159 return true; 160 } 161 162 /** 163 * Returns whether the local is live at the beginning of the given block. 164 */ 165 public abstract boolean localIsLiveIn(BciBlock block, int local); 166 167 /** 168 * Returns whether the local is set in the given loop. 169 */ 170 public abstract boolean localIsChangedInLoop(int loopId, int local); 171 172 /** 173 * Returns whether the local is live at the end of the given block. 174 */ 175 public abstract boolean localIsLiveOut(BciBlock block, int local); 176 | 59 import static org.graalvm.compiler.bytecode.Bytecodes.ILOAD_2; 60 import static org.graalvm.compiler.bytecode.Bytecodes.ILOAD_3; 61 import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE; 62 import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE_0; 63 import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE_1; 64 import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE_2; 65 import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE_3; 66 import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD; 67 import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD_0; 68 import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD_1; 69 import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD_2; 70 import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD_3; 71 import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE; 72 import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_0; 73 import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_1; 74 import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_2; 75 import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_3; 76 import static org.graalvm.compiler.bytecode.Bytecodes.RET; 77 78 import org.graalvm.compiler.bytecode.BytecodeStream; 79 import org.graalvm.compiler.debug.DebugContext; 80 import org.graalvm.compiler.java.BciBlockMapping.BciBlock; 81 82 /** 83 * Encapsulates the liveness calculation, so that subclasses for locals ≤ 64 and locals > 64 84 * can be implemented. 85 */ 86 public abstract class LocalLiveness { 87 protected final BciBlock[] blocks; 88 89 public static LocalLiveness compute(DebugContext debug, BytecodeStream stream, BciBlock[] blocks, int maxLocals, int loopCount) { 90 LocalLiveness liveness = maxLocals <= 64 ? new SmallLocalLiveness(blocks, maxLocals, loopCount) : new LargeLocalLiveness(blocks, maxLocals, loopCount); 91 liveness.computeLiveness(debug, stream); 92 return liveness; 93 } 94 95 protected LocalLiveness(BciBlock[] blocks) { 96 this.blocks = blocks; 97 } 98 99 void computeLiveness(DebugContext debug, BytecodeStream stream) { 100 for (BciBlock block : blocks) { 101 computeLocalLiveness(stream, block); 102 } 103 104 boolean changed; 105 int iteration = 0; 106 do { 107 assert traceIteration(debug, iteration); 108 changed = false; 109 for (int i = blocks.length - 1; i >= 0; i--) { 110 BciBlock block = blocks[i]; 111 int blockID = block.getId(); 112 assert traceStart(debug, block, blockID); 113 114 boolean blockChanged = (iteration == 0); 115 if (block.getSuccessorCount() > 0) { 116 int oldCardinality = liveOutCardinality(blockID); 117 for (BciBlock sux : block.getSuccessors()) { 118 assert traceSuccessor(debug, sux); 119 propagateLiveness(blockID, sux.getId()); 120 } 121 blockChanged |= (oldCardinality != liveOutCardinality(blockID)); 122 } 123 124 if (blockChanged) { 125 updateLiveness(blockID); 126 assert traceEnd(debug, block, blockID); 127 } 128 changed |= blockChanged; 129 } 130 iteration++; 131 } while (changed); 132 } 133 134 private static boolean traceIteration(DebugContext debug, int iteration) { 135 debug.log("Iteration %d", iteration); 136 return true; 137 } 138 139 private boolean traceEnd(DebugContext debug, BciBlock block, int blockID) { 140 if (debug.isLogEnabled()) { 141 debug.logv(" end B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.getId(), block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), debugLiveGen(blockID), 142 debugLiveKill(blockID)); 143 } 144 return true; 145 } 146 147 private boolean traceSuccessor(DebugContext debug, BciBlock sux) { 148 if (debug.isLogEnabled()) { 149 debug.log(" Successor B%d: %s", sux.getId(), debugLiveIn(sux.getId())); 150 } 151 return true; 152 } 153 154 private boolean traceStart(DebugContext debug, BciBlock block, int blockID) { 155 if (debug.isLogEnabled()) { 156 debug.logv(" start B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.getId(), block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), debugLiveGen(blockID), 157 debugLiveKill(blockID)); 158 } 159 return true; 160 } 161 162 /** 163 * Returns whether the local is live at the beginning of the given block. 164 */ 165 public abstract boolean localIsLiveIn(BciBlock block, int local); 166 167 /** 168 * Returns whether the local is set in the given loop. 169 */ 170 public abstract boolean localIsChangedInLoop(int loopId, int local); 171 172 /** 173 * Returns whether the local is live at the end of the given block. 174 */ 175 public abstract boolean localIsLiveOut(BciBlock block, int local); 176 |