/* generate yieldpoint without checking threadSwith request */ private static void expandUnconditionalYieldpoint(Instruction s, IR ir, RVMMethod meth) { // split the basic block after the yieldpoint, create a new // block at the end of the IR to hold the yieldpoint, // remove the yieldpoint (to prepare to out it in the new block at the end) BasicBlock thisBlock = s.getBasicBlock(); BasicBlock nextBlock = thisBlock.splitNodeWithLinksAt(s, ir); BasicBlock yieldpoint = thisBlock.createSubBlock(s.getBytecodeIndex(), ir); thisBlock.insertOut(yieldpoint); yieldpoint.insertOut(nextBlock); ir.cfg.addLastInCodeOrder(yieldpoint); s.remove(); // change thread switch instruction into call to thread switch routine // NOTE: must make s the call instruction: it is the GC point! // must also inform the GCMap that s has been moved!!! Offset offset = meth.getOffset(); LocationOperand loc = new LocationOperand(offset); Operand guard = TG(); Operand target = MemoryOperand.D(Magic.getTocPointer().plus(offset), (byte) 4, loc, guard); MIR_Call.mutate0(s, CALL_SAVE_VOLATILE, null, null, target, MethodOperand.STATIC(meth)); yieldpoint.appendInstruction(s); ir.MIRInfo.gcIRMap.moveToEnd(s); yieldpoint.appendInstruction(MIR_Branch.create(IA32_JMP, nextBlock.makeJumpTarget())); // make a jump to yield block thisBlock.appendInstruction(MIR_Branch.create(IA32_JMP, yieldpoint.makeJumpTarget())); }
private static void expandYieldpoint( Instruction s, IR ir, RVMMethod meth, IA32ConditionOperand ypCond) { // split the basic block after the yieldpoint, create a new // block at the end of the IR to hold the yieldpoint, // remove the yieldpoint (to prepare to out it in the new block at the end) BasicBlock thisBlock = s.getBasicBlock(); BasicBlock nextBlock = thisBlock.splitNodeWithLinksAt(s, ir); BasicBlock yieldpoint = thisBlock.createSubBlock(s.getBytecodeIndex(), ir, 0); thisBlock.insertOut(yieldpoint); yieldpoint.insertOut(nextBlock); ir.cfg.addLastInCodeOrder(yieldpoint); s.remove(); // change thread switch instruction into call to thread switch routine // NOTE: must make s the call instruction: it is the GC point! // must also inform the GCMap that s has been moved!!! Offset offset = meth.getOffset(); LocationOperand loc = new LocationOperand(offset); Operand guard = TG(); Operand target; if (JTOC_REGISTER == null) { target = MemoryOperand.D(Magic.getTocPointer().plus(offset), (byte) 4, loc, guard); } else { target = MemoryOperand.BD(ir.regpool.makeTocOp().asRegister(), offset, (byte) 8, loc, guard); } MIR_Call.mutate0(s, CALL_SAVE_VOLATILE, null, null, target, MethodOperand.STATIC(meth)); yieldpoint.appendInstruction(s); ir.MIRInfo.gcIRMap.moveToEnd(s); yieldpoint.appendInstruction(MIR_Branch.create(IA32_JMP, nextBlock.makeJumpTarget())); // Check to see if threadSwitch requested Offset tsr = Entrypoints.takeYieldpointField.getOffset(); MemoryOperand M = MemoryOperand.BD(ir.regpool.makeTROp(), tsr, (byte) 4, null, null); thisBlock.appendInstruction(MIR_Compare.create(IA32_CMP, M, IC(0))); thisBlock.appendInstruction( MIR_CondBranch.create( IA32_JCC, ypCond, yieldpoint.makeJumpTarget(), BranchProfileOperand.never())); }