159 void computeLocalLiveSets() { 160 int liveSize = allocator.liveSetSize(); 161 162 intervalInLoop = new BitMap2D(allocator.operandSize(), allocator.numLoops()); 163 164 try { 165 final BitSet liveGenScratch = new BitSet(liveSize); 166 final BitSet liveKillScratch = new BitSet(liveSize); 167 // iterate all blocks 168 for (final AbstractBlockBase<?> block : allocator.sortedBlocks()) { 169 try (Indent indent = debug.logAndIndent("compute local live sets for block %s", block)) { 170 171 liveGenScratch.clear(); 172 liveKillScratch.clear(); 173 174 ArrayList<LIRInstruction> instructions = allocator.getLIR().getLIRforBlock(block); 175 int numInst = instructions.size(); 176 177 ValueConsumer useConsumer = (operand, mode, flags) -> { 178 if (isVariable(operand)) { 179 int operandNum = allocator.operandNumber(operand); 180 if (!liveKillScratch.get(operandNum)) { 181 liveGenScratch.set(operandNum); 182 if (debug.isLogEnabled()) { 183 debug.log("liveGen for operand %d(%s)", operandNum, operand); 184 } 185 } 186 if (block.getLoop() != null) { 187 intervalInLoop.setBit(operandNum, block.getLoop().getIndex()); 188 } 189 } 190 191 if (allocator.detailedAsserts) { 192 verifyInput(block, liveKillScratch, operand); 193 } 194 }; 195 ValueConsumer stateConsumer = (operand, mode, flags) -> { 196 if (LinearScan.isVariableOrRegister(operand)) { 197 int operandNum = allocator.operandNumber(operand); 198 if (!liveKillScratch.get(operandNum)) { 199 liveGenScratch.set(operandNum); 200 if (debug.isLogEnabled()) { 201 debug.log("liveGen in state for operand %d(%s)", operandNum, operand); 202 } 203 } 204 } 205 }; 206 ValueConsumer defConsumer = (operand, mode, flags) -> { 207 if (isVariable(operand)) { 208 int varNum = allocator.operandNumber(operand); 209 liveKillScratch.set(varNum); 210 if (debug.isLogEnabled()) { 211 debug.log("liveKill for operand %d(%s)", varNum, operand); 212 } 213 if (block.getLoop() != null) { 214 intervalInLoop.setBit(varNum, block.getLoop().getIndex()); 215 } 216 } 217 218 if (allocator.detailedAsserts) { 219 /* 220 * Fixed intervals are never live at block boundaries, so they need not 221 * be processed in live sets. Process them only in debug mode so that 222 * this can be checked 223 */ 224 verifyTemp(liveKillScratch, operand); 225 } 226 }; 227 228 // iterate all instructions of the block 251 252 if (debug.isLogEnabled()) { 253 debug.log("liveGen B%d %s", block.getId(), blockSets.liveGen); 254 debug.log("liveKill B%d %s", block.getId(), blockSets.liveKill); 255 } 256 257 } 258 } // end of block iteration 259 } catch (OutOfMemoryError oom) { 260 throw new PermanentBailoutException(oom, "Out-of-memory during live set allocation of size %d", liveSize); 261 } 262 } 263 264 private void verifyTemp(BitSet liveKill, Value operand) { 265 /* 266 * Fixed intervals are never live at block boundaries, so they need not be processed in live 267 * sets. Process them only in debug mode so that this can be checked 268 */ 269 if (isRegister(operand)) { 270 if (allocator.isProcessed(operand)) { 271 liveKill.set(allocator.operandNumber(operand)); 272 } 273 } 274 } 275 276 private void verifyInput(AbstractBlockBase<?> block, BitSet liveKill, Value operand) { 277 /* 278 * Fixed intervals are never live at block boundaries, so they need not be processed in live 279 * sets. This is checked by these assertions to be sure about it. The entry block may have 280 * incoming values in registers, which is ok. 281 */ 282 if (isRegister(operand) && block != allocator.getLIR().getControlFlowGraph().getStartBlock()) { 283 if (allocator.isProcessed(operand)) { 284 assert liveKill.get(allocator.operandNumber(operand)) : "using fixed register " + asRegister(operand) + " that is not defined in this block " + block; 285 } 286 } 287 } 288 289 /** 290 * Performs a backward dataflow analysis to compute global live sets (i.e. 291 * {@link BlockData#liveIn} and {@link BlockData#liveOut}) for each block. 292 */ 293 @SuppressWarnings("try") 294 protected void computeGlobalLiveSets() { 295 try (Indent indent = debug.logAndIndent("compute global live sets")) { 296 int numBlocks = allocator.blockCount(); 297 boolean changeOccurred; 298 boolean changeOccurredInBlock; 299 int iterationCount = 0; 300 BitSet scratch = new BitSet(allocator.liveSetSize()); // scratch set for calculations 301 302 /* 303 * Perform a backward dataflow analysis to compute liveOut and liveIn for each block. 304 * The loop is executed until a fixpoint is reached (no changes in an iteration). 305 */ 306 do { | 159 void computeLocalLiveSets() { 160 int liveSize = allocator.liveSetSize(); 161 162 intervalInLoop = new BitMap2D(allocator.operandSize(), allocator.numLoops()); 163 164 try { 165 final BitSet liveGenScratch = new BitSet(liveSize); 166 final BitSet liveKillScratch = new BitSet(liveSize); 167 // iterate all blocks 168 for (final AbstractBlockBase<?> block : allocator.sortedBlocks()) { 169 try (Indent indent = debug.logAndIndent("compute local live sets for block %s", block)) { 170 171 liveGenScratch.clear(); 172 liveKillScratch.clear(); 173 174 ArrayList<LIRInstruction> instructions = allocator.getLIR().getLIRforBlock(block); 175 int numInst = instructions.size(); 176 177 ValueConsumer useConsumer = (operand, mode, flags) -> { 178 if (isVariable(operand)) { 179 int operandNum = getOperandNumber(operand); 180 if (!liveKillScratch.get(operandNum)) { 181 liveGenScratch.set(operandNum); 182 if (debug.isLogEnabled()) { 183 debug.log("liveGen for operand %d(%s)", operandNum, operand); 184 } 185 } 186 if (block.getLoop() != null) { 187 intervalInLoop.setBit(operandNum, block.getLoop().getIndex()); 188 } 189 } 190 191 if (allocator.detailedAsserts) { 192 verifyInput(block, liveKillScratch, operand); 193 } 194 }; 195 ValueConsumer stateConsumer = (operand, mode, flags) -> { 196 if (LinearScan.isVariableOrRegister(operand)) { 197 int operandNum = getOperandNumber(operand); 198 if (!liveKillScratch.get(operandNum)) { 199 liveGenScratch.set(operandNum); 200 if (debug.isLogEnabled()) { 201 debug.log("liveGen in state for operand %d(%s)", operandNum, operand); 202 } 203 } 204 } 205 }; 206 ValueConsumer defConsumer = (operand, mode, flags) -> { 207 if (isVariable(operand)) { 208 int varNum = getOperandNumber(operand); 209 liveKillScratch.set(varNum); 210 if (debug.isLogEnabled()) { 211 debug.log("liveKill for operand %d(%s)", varNum, operand); 212 } 213 if (block.getLoop() != null) { 214 intervalInLoop.setBit(varNum, block.getLoop().getIndex()); 215 } 216 } 217 218 if (allocator.detailedAsserts) { 219 /* 220 * Fixed intervals are never live at block boundaries, so they need not 221 * be processed in live sets. Process them only in debug mode so that 222 * this can be checked 223 */ 224 verifyTemp(liveKillScratch, operand); 225 } 226 }; 227 228 // iterate all instructions of the block 251 252 if (debug.isLogEnabled()) { 253 debug.log("liveGen B%d %s", block.getId(), blockSets.liveGen); 254 debug.log("liveKill B%d %s", block.getId(), blockSets.liveKill); 255 } 256 257 } 258 } // end of block iteration 259 } catch (OutOfMemoryError oom) { 260 throw new PermanentBailoutException(oom, "Out-of-memory during live set allocation of size %d", liveSize); 261 } 262 } 263 264 private void verifyTemp(BitSet liveKill, Value operand) { 265 /* 266 * Fixed intervals are never live at block boundaries, so they need not be processed in live 267 * sets. Process them only in debug mode so that this can be checked 268 */ 269 if (isRegister(operand)) { 270 if (allocator.isProcessed(operand)) { 271 liveKill.set(getOperandNumber(operand)); 272 } 273 } 274 } 275 276 private void verifyInput(AbstractBlockBase<?> block, BitSet liveKill, Value operand) { 277 /* 278 * Fixed intervals are never live at block boundaries, so they need not be processed in live 279 * sets. This is checked by these assertions to be sure about it. The entry block may have 280 * incoming values in registers, which is ok. 281 */ 282 if (isRegister(operand) && block != allocator.getLIR().getControlFlowGraph().getStartBlock()) { 283 if (allocator.isProcessed(operand)) { 284 assert liveKill.get(getOperandNumber(operand)) : "using fixed register " + asRegister(operand) + " that is not defined in this block " + block; 285 } 286 } 287 } 288 289 protected int getOperandNumber(Value operand) { 290 return allocator.operandNumber(operand); 291 } 292 293 /** 294 * Performs a backward dataflow analysis to compute global live sets (i.e. 295 * {@link BlockData#liveIn} and {@link BlockData#liveOut}) for each block. 296 */ 297 @SuppressWarnings("try") 298 protected void computeGlobalLiveSets() { 299 try (Indent indent = debug.logAndIndent("compute global live sets")) { 300 int numBlocks = allocator.blockCount(); 301 boolean changeOccurred; 302 boolean changeOccurredInBlock; 303 int iterationCount = 0; 304 BitSet scratch = new BitSet(allocator.liveSetSize()); // scratch set for calculations 305 306 /* 307 * Perform a backward dataflow analysis to compute liveOut and liveIn for each block. 308 * The loop is executed until a fixpoint is reached (no changes in an iteration). 309 */ 310 do { |