From: <mic...@us...> - 2007-05-18 17:15:07
|
Revision: 123 http://svn.sourceforge.net/pearcolator/?rev=123&view=rev Author: michael_baer Date: 2007-05-18 10:13:21 -0700 (Fri, 18 May 2007) Log Message: ----------- Further refined branch resolution: - centralized the decision on whether to include a branch target into the trace or not - harmonized the way branch targets are resolved and the call interface to the decoder - re-introduced a code cache in the ProcessSpace class Misc. changes: - allowing custom functions calls within traces (untested) ARM changes: - fixed a bug where flags in RSBS would be set incorrectly Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/Main.java src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java src/org/binarytranslator/arch/x86/decoder/X862IR.java src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java src/org/binarytranslator/generic/execution/DynamicTranslationController.java src/org/binarytranslator/generic/memory/CallBasedMemory.java src/org/binarytranslator/generic/memory/DebugMemory.java src/org/binarytranslator/generic/memory/MemoryMapException.java src/org/binarytranslator/generic/os/process/ProcessSpace.java src/org/binarytranslator/vmInterface/DBT_Trace.java Added Paths: ----------- src/org/binarytranslator/generic/decoder/CodeCache.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/DBT_Options.java 2007-05-18 17:13:21 UTC (rev 123) @@ -17,8 +17,10 @@ * Options for controlling the emulator */ public class DBT_Options { - // -oO Runtime settings Oo- + /** Remove features that will only work on jikes? */ + public final static boolean buildForSunVM = true; + /** * Debug binary loading */ @@ -69,19 +71,10 @@ */ public static boolean plantUncaughtBranchWatcher = false; - /** - * Should all branches (excluding to lr and ctr) be resolved in one big go or - * one at at a time - */ - public static boolean resolveBranchesAtOnce = true; + /** Should direct branches be resolved before dynamic branches? */ + public static boolean resolveDirectBranchesFirst = true; /** - * Should procedures (branches to ctr and lr) be given precedent over more - * local branches - */ - public static boolean resolveProceduresBeforeBranches = true; - - /** * Use global branch information rather than local (within the trace) * information when optimisation level is greater than or equal to this value */ @@ -231,14 +224,8 @@ instrOpt2 = Integer.parseInt(value); } else if (arg.equalsIgnoreCase("-X:dbt:singleInstrTranslation")) { singleInstrTranslation = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("-X:dbt:resolveBranchesAtOnce")) { - resolveBranchesAtOnce = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("-X:dbt:resolveBranchesAtOnce")) { - resolveBranchesAtOnce = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("-X:dbt:resolveProceduresBeforeBranches")) { - resolveProceduresBeforeBranches = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("-X:dbt:resolveProceduresBeforeBranches")) { - resolveProceduresBeforeBranches = Boolean.parseBoolean(value); + } else if (arg.equalsIgnoreCase("-X:dbt:resolveDirectBranchesFirst")) { + resolveDirectBranchesFirst = Boolean.parseBoolean(value); } else if (arg.equalsIgnoreCase("-X:dbt:gdbStub")) { gdbStub = Boolean.parseBoolean(value); } else if (arg.equalsIgnoreCase("-X:dbt:gdbStubPort")) { Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/Main.java 2007-05-18 17:13:21 UTC (rev 123) @@ -10,11 +10,15 @@ import java.io.File; -import org.binarytranslator.arch.arm.decoder.Utils; import org.binarytranslator.generic.execution.DynamicTranslationController; import org.binarytranslator.generic.execution.ExecutionController; import org.binarytranslator.generic.execution.GdbController; import org.binarytranslator.generic.execution.InterpreterController; +import org.binarytranslator.generic.execution.ThreadedInterpretationController; +import org.binarytranslator.generic.execution.ThreadedInterpretationController2; +import org.binarytranslator.generic.execution.ThreadedInterpretationController3; +import org.binarytranslator.generic.execution.ThreadedInterpretationController4; +import org.binarytranslator.generic.execution.ThreadedInterpretationController5; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -98,15 +102,18 @@ //Create an execution controller and pass execution on to it ExecutionController controller; - if (DBT_Options.gdbStub) { - controller = new GdbController(DBT_Options.gdbStubPort, ps); + if (DBT_Options.buildForSunVM) { + controller = new InterpreterController(ps); } else { - controller = new DynamicTranslationController(ps); + if (DBT_Options.gdbStub) { + controller = new GdbController(DBT_Options.gdbStubPort, ps); + } + else { + controller = new DynamicTranslationController(ps); + } } - - //controller = new InterpreterController(ps); controller.run(); System.out.println("\nProgram has finished."); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-18 17:13:21 UTC (rev 123) @@ -9,6 +9,7 @@ import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode; import org.binarytranslator.generic.decoder.AbstractCodeTranslator; import org.binarytranslator.generic.decoder.Laziness; +import org.binarytranslator.vmInterface.DBT_Trace; import org.jikesrvm.classloader.VM_Atom; import org.jikesrvm.classloader.VM_FieldReference; import org.jikesrvm.classloader.VM_MemberReference; @@ -129,8 +130,8 @@ if (DBT.VerifyAssertions) DBT._assert(registers_overflowFlag_Fref != null); } - public ARM2IR(OPT_GenerationContext context) { - super(context); + public ARM2IR(OPT_GenerationContext context, DBT_Trace trace) { + super(context, trace); translator = new ARM_Translator((ARM_ProcessSpace)ps, this); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-18 17:13:21 UTC (rev 123) @@ -889,16 +889,16 @@ } else { OPT_Instruction s = createCallToRegisters("restoreSPSR2CPSR", "()V", 0); - arm2ir.appendInstruction(s); + arm2ir.appendCustomCall(s); } } if (Rd == 15) { if (updateConditionCodes) - arm2ir.appendDynamicJump(result, lazy, BranchType.INDIRECT_BRANCH); + arm2ir.appendBranch(result, lazy, BranchType.INDIRECT_BRANCH); else - arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); + arm2ir.appendTraceExit(lazy, result); } else { arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result) ); @@ -941,16 +941,15 @@ } else { OPT_Instruction s = createCallToRegisters("restoreSPSR2CPSR", "()V", 0); - arm2ir.appendInstruction(s); + arm2ir.appendCustomCall(s); } } if (Rd == 15) { - if (updateConditionCodes) - arm2ir.appendDynamicJump(result, lazy, BranchType.INDIRECT_BRANCH); + arm2ir.appendBranch(result, lazy, BranchType.INDIRECT_BRANCH); else - arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); + arm2ir.appendTraceExit(lazy, result); } else { arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result) ); @@ -968,9 +967,9 @@ */ protected final void setSubFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { //set the carry flag to not(Borrow) + OPT_ConditionOperand notBorrowFromSub = OPT_ConditionOperand.BORROW_FROM_SUB().flipCode(); arm2ir.appendInstruction(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, OPT_ConditionOperand.BORROW_FROM_SUB(), new OPT_BranchProfileOperand())); - arm2ir.appendInstruction(Unary.create(BOOLEAN_NOT, arm2ir.getCarryFlag(), arm2ir.getCarryFlag())); + BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, notBorrowFromSub, new OPT_BranchProfileOperand())); //set the overflow flag arm2ir.appendInstruction(BooleanCmp.create( @@ -1021,15 +1020,13 @@ setLogicalFlags(result); } else { OPT_Instruction s = createCallToRegisters("restoreSPSR2CPSR", "()V", 0); - arm2ir.appendInstruction(s); + arm2ir.appendCustomCall(s); } } - - if (Rd == 15) { if (updateConditionCodes) { - arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); + arm2ir.appendTraceExit(lazy, result); } else { BranchType branchType = BranchType.INDIRECT_BRANCH; @@ -1038,7 +1035,7 @@ if (opcode == Opcode.MOV && operand2.getType() == OperandWrapper.Type.Register && operand2.getRegister() == ARM_Registers.LR) branchType = BranchType.RETURN; - arm2ir.appendDynamicJump(result, lazy, branchType); + arm2ir.appendBranch(result, lazy, branchType); } } else { @@ -1284,6 +1281,7 @@ OPT_Operand operand1 = resolveOperand1(); OPT_Operand operand2 = resolveOperand2(); OPT_RegisterOperand result = arm2ir.getTempInt(0); + arm2ir.appendInstruction(Binary.create(INT_SUB, result, operand1, operand2)); setSubFlags(result, operand1, operand2); } @@ -1302,6 +1300,7 @@ OPT_Operand operand1 = resolveOperand1(); OPT_Operand operand2 = resolveOperand2(); OPT_RegisterOperand result = arm2ir.getTempInt(0); + arm2ir.appendInstruction(Binary.create(INT_ADD, result, operand1, operand2)); setAddFlags(result, operand1, operand2); } @@ -1358,6 +1357,7 @@ OPT_RegisterOperand result = getResultRegister(); OPT_RegisterOperand tmp = arm2ir.getTempInt(0); + arm2ir.appendInstruction(Unary.create(INT_NOT, tmp, operand2)); arm2ir.appendInstruction(Binary.create(INT_AND, result, operand1, tmp)); setLogicalResult(result); @@ -1494,7 +1494,7 @@ //This instruction gets very complex when forceUser is set, which is why we are interpreting that special and rare instruction if (forceUser) { arm2ir.appendInterpretedInstruction(pc, lazy); - arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, arm2ir.getRegister(ARM_Registers.PC)); + arm2ir.appendTraceExit(lazy, arm2ir.getRegister(ARM_Registers.PC)); return; } @@ -1571,7 +1571,7 @@ switchToThumbBlock.insertOut(finishInstruction); OPT_Instruction call_setThumbMode = createCallToRegisters("setThumbMode", "(Z)V", 1); Call.setParam(call_setThumbMode, 1, new OPT_IntConstantOperand(1)); - arm2ir.appendInstruction(call_setThumbMode); + arm2ir.appendCustomCall(call_setThumbMode); arm2ir.appendInstruction(Goto.create(GOTO, finishInstruction.makeJumpTarget())); //No, don't switch to thumb mode @@ -1580,12 +1580,12 @@ arm2ir.appendInstruction(Binary.create(INT_AND, regPC, regPC, new OPT_IntConstantOperand(0xFFFFFFFE))); OPT_Instruction call_setArmMode = createCallToRegisters("setThumbMode", "(Z)V", 1); Call.setParam(call_setArmMode, 1, new OPT_IntConstantOperand(0)); - arm2ir.appendInstruction(call_setArmMode); + arm2ir.appendCustomCall(call_setArmMode); arm2ir.appendInstruction(Goto.create(GOTO, finishInstruction.makeJumpTarget())); //according to the APCS, these types of instructions are usually function returns arm2ir.setCurrentBlock(finishInstruction); - arm2ir.appendDynamicJump(regPC, lazy, BranchType.RETURN); + arm2ir.appendBranch(regPC, lazy, BranchType.RETURN); return; } } else { @@ -1658,9 +1658,12 @@ if (link) { arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(pc + 4))); } + else { + //we should never be returning from the goto + arm2ir.getCurrentBlock().deleteNormalOut(); + } - arm2ir.getCurrentBlock().deleteNormalOut(); - arm2ir.appendGoto(pc + getOffset() + 8, lazy, link ? BranchType.CALL : BranchType.DIRECT_BRANCH); + arm2ir.appendBranch(pc + getOffset() + 8, lazy, link ? BranchType.CALL : BranchType.DIRECT_BRANCH); } public int getSuccessor(int pc) { @@ -1718,11 +1721,11 @@ //set the correct processor mode (thumb or not) OPT_Instruction s = createCallToRegisters("setThumbMode", "(Z)V", 1); Call.setParam(s, 1, enableThumb); - arm2ir.appendInstruction(s); + arm2ir.appendCustomCall(s); //jump to the target address. Because we might have switched to thumb mode, we are //ending the trace with this method - arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, targetAddress); + arm2ir.appendTraceExit(lazy, targetAddress); } public int getSuccessor(int pc) { @@ -1856,7 +1859,7 @@ } Call.setResult(call, psrValue); - arm2ir.appendInstruction(call); + arm2ir.appendCustomCall(call); } public int getSuccessor(int pc) { @@ -1892,7 +1895,7 @@ public void translate() { arm2ir.appendSystemCall(lazy, pc); - arm2ir.appendDynamicJump(arm2ir.getRegister(ARM_Registers.PC), lazy, BranchType.INDIRECT_BRANCH); + arm2ir.appendBranch(arm2ir.getRegister(ARM_Registers.PC), lazy, BranchType.INDIRECT_BRANCH); } public int getSuccessor(int pc) { @@ -1957,12 +1960,12 @@ currentOperatingMode = arm2ir.getTempOperatingMode(); Call.setResult(call_getOperatingMode, currentOperatingMode); - arm2ir.appendInstruction(call_getOperatingMode); + arm2ir.appendCustomCall(call_getOperatingMode); OPT_Instruction call_setOperatingModeWithoutRegisterLayout = createCallToRegisters("setOperatingModeWithoutRegisterLayout", "(A)", 1); Call.setParam(call_setOperatingModeWithoutRegisterLayout, 1, arm2ir.getTempOperatingMode(OperatingMode.USR)); - arm2ir.appendInstruction(call_setOperatingModeWithoutRegisterLayout); + arm2ir.appendCustomCall(call_setOperatingModeWithoutRegisterLayout); } //get the address of the memory, that we're supposed access @@ -2040,7 +2043,7 @@ if (forceUserMode) { OPT_Instruction call_setOperatingModeWithoutRegisterLayout = createCallToRegisters("setOperatingModeWithoutRegisterLayout", "(A)", 1); Call.setParam(call_setOperatingModeWithoutRegisterLayout, 1, currentOperatingMode); - arm2ir.appendInstruction(call_setOperatingModeWithoutRegisterLayout); + arm2ir.appendCustomCall(call_setOperatingModeWithoutRegisterLayout); } //should the memory address, which we accessed, be written back into a register? @@ -2060,7 +2063,7 @@ if (isLoad && Rd == ARM_Registers.PC) { //we are actually loading to the program counter here - arm2ir.appendDynamicJump(arm2ir.getRegister(Rd), lazy, BranchType.INDIRECT_BRANCH); + arm2ir.appendBranch(arm2ir.getRegister(Rd), lazy, BranchType.INDIRECT_BRANCH); } } Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-05-18 17:13:21 UTC (rev 123) @@ -8,9 +8,11 @@ import org.binarytranslator.arch.arm.os.process.image.ARM_ImageProcessSpace; import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; import org.binarytranslator.generic.decoder.Interpreter; +import org.binarytranslator.generic.memory.ByteAddressedMemory; import org.binarytranslator.generic.memory.DebugMemory; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.process.ProcessSpace; +import org.binarytranslator.vmInterface.DBT_Trace; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; import org.vmmagic.pragma.Uninterruptible; @@ -37,7 +39,11 @@ protected ARM_ProcessSpace() { registers = new ARM_Registers(); - memory = new DebugMemory(); + + if (DBT_Options.buildForSunVM) + memory = new DebugMemory(); + else + memory = new ByteAddressedMemory(); } /** @@ -48,8 +54,8 @@ * the generation context for the HIR generation * @return a HIR generator */ - public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context) { - return new ARM2IR(context); + public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context, DBT_Trace trace) { + return new ARM2IR(context, trace); } /** Modified: src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-05-18 17:13:21 UTC (rev 123) @@ -17,6 +17,7 @@ import org.binarytranslator.generic.decoder.AbstractCodeTranslator; import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; +import org.binarytranslator.vmInterface.DBT_Trace; import org.jikesrvm.classloader.VM_Atom; import org.jikesrvm.classloader.VM_FieldReference; import org.jikesrvm.classloader.VM_MemberReference; @@ -253,8 +254,8 @@ * Construct the PPC2IR object for the generation context; then we'll be ready * to start generating the HIR. */ - public PPC2IR(OPT_GenerationContext context) { - super(context); + public PPC2IR(OPT_GenerationContext context, DBT_Trace trace) { + super(context, trace); // Create register maps PPC -> OPT_Register intRegMap = new OPT_Register[32]; intRegInUseMap = new boolean[32]; Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-05-18 17:13:21 UTC (rev 123) @@ -4026,7 +4026,7 @@ branchAddress = ppc2ir.getLRRegister(); } - ppc2ir.appendDynamicJump(branchAddress, lazy, BranchLogic.BranchType.RETURN); + ppc2ir.appendBranch(branchAddress, lazy, BranchLogic.BranchType.RETURN); // stop translation on branch always if (BO == 0x14) { @@ -4672,7 +4672,7 @@ } OPT_RegisterOperand branchAddress = ppc2ir.getCTRRegister(); - ppc2ir.appendDynamicJump(branchAddress, lazy, BranchType.INDIRECT_BRANCH); + ppc2ir.appendBranch(branchAddress, lazy, BranchType.INDIRECT_BRANCH); // stop translation on branch always @@ -11705,7 +11705,7 @@ if ((LK == 0) || ppc2ir.traceContinuesAfterBranchAndLink(pc)) { // Plant branch block - ppc2ir.appendGoto(target_address, lazy, LK != 0 ? BranchType.CALL : BranchType.DIRECT_BRANCH); + ppc2ir.appendBranch(target_address, lazy, LK != 0 ? BranchType.CALL : BranchType.DIRECT_BRANCH); // stop translation on branch always if (BO == 0x14) { @@ -11724,14 +11724,14 @@ ppc2ir.setCurrentBlock(instructionEndBlock); ppc2ir.setNextBlock(ppc2ir.createBlockAfterCurrent()); - ppc2ir.appendGoto(pc + 4, lazy, BranchType.DIRECT_BRANCH); + ppc2ir.appendBranch(pc + 4, lazy, BranchType.DIRECT_BRANCH); return target_address; } } } else { // This was a branch and link and the trace should stop, so end // gracefully - ppc2ir.appendGoto(target_address, lazy, BranchType.CALL); + ppc2ir.appendBranch(target_address, lazy, BranchType.CALL); return -1; } } @@ -11804,7 +11804,7 @@ if (ppc2ir.traceContinuesAfterBranchAndLink(pc)) { return target_addr; } else { - ppc2ir.setReturnValueResolveLazinessAndBranchToFinish( + ppc2ir.appendTraceExit( (PPC_Laziness) lazy.clone(), new OPT_IntConstantOperand(target_addr)); return -1; Modified: src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-05-18 17:13:21 UTC (rev 123) @@ -20,6 +20,7 @@ import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; +import org.binarytranslator.vmInterface.DBT_Trace; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; import org.jikesrvm.ppc.PPC_Disassembler; @@ -139,8 +140,8 @@ * the generation context for the HIR generation * @return a HIR generator */ - public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context) { - return new PPC2IR(context); + public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context, DBT_Trace trace) { + return new PPC2IR(context, trace); } /** Modified: src/org/binarytranslator/arch/x86/decoder/X862IR.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-05-18 17:13:21 UTC (rev 123) @@ -16,6 +16,7 @@ import org.binarytranslator.generic.decoder.AbstractCodeTranslator; import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; +import org.binarytranslator.vmInterface.DBT_Trace; import org.jikesrvm.classloader.VM_Atom; import org.jikesrvm.classloader.VM_BootstrapClassLoader; import org.jikesrvm.classloader.VM_FieldReference; @@ -100,8 +101,8 @@ /** * Constructor */ - public X862IR(OPT_GenerationContext context) { - super(context); + public X862IR(OPT_GenerationContext context, DBT_Trace trace) { + super(context, trace); // Create the registers SegReg = new OPT_Register[6]; @@ -147,7 +148,7 @@ appendInstruction(Binary.create(INT_ADD, esp, esp.copyRO(), new OPT_IntConstantOperand(4))); // Branch - setReturnValueResolveLazinessAndBranchToFinish((X86_Laziness) lazy.clone(), temp.copyRO()); + appendTraceExit((X86_Laziness) lazy.clone(), temp.copyRO()); return -1; } Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-05-18 17:13:21 UTC (rev 123) @@ -3649,7 +3649,7 @@ stack.writeValue(translationHelper, lazy, temp.copyRO()); // Branch - translationHelper.appendDynamicJump(destOp.copyRO(), lazy, BranchType.CALL); + translationHelper.appendBranch(destOp.copyRO(), lazy, BranchType.CALL); return -1; } @@ -3770,7 +3770,7 @@ translationHelper.appendInstruction(Binary.create(INT_ADD, esp, esp.copyRO(), new OPT_IntConstantOperand(4 + immediate))); // Branch - translationHelper.setReturnValueResolveLazinessAndBranchToFinish( + translationHelper.appendTraceExit( (X86_Laziness) lazy.clone(), temp.copyRO()); return -1; } @@ -4035,7 +4035,7 @@ translationHelper.appendInstruction(gotoInstr); translationHelper.setCurrentBlock(executeBranch); - translationHelper.appendGoto(target_address, lazy, BranchType.DIRECT_BRANCH); + translationHelper.appendBranch(target_address, lazy, BranchType.DIRECT_BRANCH); translationHelper.setCurrentBlock(fallThrough); return pc + length; @@ -4169,7 +4169,7 @@ if (modrm == null) { target_address = absolute ? immediate : pc + length + immediate; translationHelper.getCurrentBlock().deleteNormalOut(); - translationHelper.appendGoto(target_address, lazy, BranchType.DIRECT_BRANCH); + translationHelper.appendBranch(target_address, lazy, BranchType.DIRECT_BRANCH); } else { int operandSize; if (prefix3 == null) { @@ -4210,7 +4210,7 @@ * ppc2ir.setCurrentBlock(fallThrough); * ppc2ir.plantRecordUncaughtBcctr(pc, branchAddress.copyRO()); */ - translationHelper.setReturnValueResolveLazinessAndBranchToFinish( + translationHelper.appendTraceExit( (X86_Laziness) lazy.clone(), branchAddress.copyRO()); } return -1; Modified: src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-05-18 17:13:21 UTC (rev 123) @@ -19,7 +19,6 @@ import org.binarytranslator.generic.memory.ByteAddressedMemory; import org.binarytranslator.generic.execution.GdbController.GdbTarget; import org.binarytranslator.generic.fault.BadInstructionException; -import org.binarytranslator.arch.ppc.decoder.PPC_InstructionDecoder; import org.binarytranslator.arch.x86.os.process.linux.X86_LinuxProcessSpace; import org.binarytranslator.arch.x86.decoder.X862IR; import org.binarytranslator.arch.x86.decoder.X86_InstructionDecoder; @@ -150,8 +149,8 @@ * @param context the generation context for the HIR generation * @return a HIR generator */ - public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context) { - return new X862IR(context); + public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context, DBT_Trace trace) { + return new X862IR(context, trace); } /** Modified: src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-05-18 17:13:21 UTC (rev 123) @@ -21,6 +21,7 @@ import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DBT_Trace; import org.jikesrvm.classloader.VM_Atom; +import org.jikesrvm.classloader.VM_BytecodeConstants; import org.jikesrvm.classloader.VM_Class; import org.jikesrvm.classloader.VM_MemberReference; import org.jikesrvm.classloader.VM_Method; @@ -75,30 +76,22 @@ */ public abstract class AbstractCodeTranslator implements OPT_Constants, OPT_Operators { - /** - * VM_TypeReference of org.binarytranslator.generic.os.process.ProcessSpace - */ + /** The trace that we're currently translating code for. */ + protected final DBT_Trace trace; + + /** VM_TypeReference of org.binarytranslator.generic.os.process.ProcessSpace */ private static final VM_TypeReference psTref; - /** - * Method ProcessSpace.doSysCall - */ + /** Method ProcessSpace.doSysCall */ public static final VM_Method sysCallMethod; - /** - * VM_TypeReference of - * org.binarytranslator.generic.fault.BadInstructionException - */ + /** VM_TypeReference of org.binarytranslator.generic.fault.BadInstructionException */ public static final VM_Class badInstrKlass; - /** - * Method BadInstructionException.<init> - */ + /** Method BadInstructionException.<init> */ public static final VM_Method badInstrKlassInitMethod; - /** - * Method ProcessSpace.recordUncaughtBranchBadInstructionException.<init> - */ + /** Method ProcessSpace.recordUncaughtBranchBadInstructionException.<init> */ public static final VM_Method recordUncaughtBranchMethod; static { @@ -165,20 +158,25 @@ public final OPT_Instruction instruction; public final Laziness lazyStateAtJump; public final int pc; + public final BranchType type; - public UnresolvedJumpInstruction(OPT_Instruction instruction, Laziness lazyStateAtJump, int pc) { + public UnresolvedJumpInstruction(OPT_Instruction instruction, Laziness lazyStateAtJump, int pc, BranchType type) { this.instruction = instruction; this.lazyStateAtJump = lazyStateAtJump; this.pc = pc; + this.type = type; } } - /** List of unresolved Goto instructions */ - private final ArrayList<UnresolvedJumpInstruction> unresolvedGoto; - + /** + * List of unresolved direct branches. The destinations of direct branches are already known at + * translation time.*/ + private final ArrayList<UnresolvedJumpInstruction> unresolvedDirectBranches; - /** List of unresolved dynamic jumps */ - private final ArrayList<UnresolvedJumpInstruction> unresolvedDynamicJumps; + /** + * List of unresolved dynamic branches. Dynamics branches have a destination address that is only + * determined at runtime. */ + private final ArrayList<UnresolvedJumpInstruction> unresolvedDynamicBranches; /** * Constructor @@ -186,7 +184,11 @@ * @param context * The JRVM generation context for this trace. */ - protected AbstractCodeTranslator(OPT_GenerationContext context) { + protected AbstractCodeTranslator(OPT_GenerationContext context, DBT_Trace trace) { + + //Store the trace that we're invoked from + this.trace = trace; + // Make copies of popular variables gc = context; ps = ((DBT_Trace) (gc.method)).ps; @@ -202,14 +204,12 @@ // Create preFillBlock, currentBlock and finishBlock gc.prologue.insertOut(gc.epilogue); preFillBlock = createBlockAfter(gc.prologue); - currentBlock = createBlockAfter(preFillBlock); - finishBlock = createBlockAfterCurrent(); // Fix up stores - unresolvedGoto = new ArrayList<UnresolvedJumpInstruction>(); - unresolvedDynamicJumps = new ArrayList<UnresolvedJumpInstruction>(); + unresolvedDirectBranches = new ArrayList<UnresolvedJumpInstruction>(); + unresolvedDynamicBranches = new ArrayList<UnresolvedJumpInstruction>(); } /** Returns the number of previously translated instructions within this trace. */ @@ -227,27 +227,19 @@ // Translating the subtrace finished so resolve any unresolved // branches - do { - if (DBT_Options.resolveProceduresBeforeBranches) { - resolveAllDynamicJumpTargets(); - } - if (DBT_Options.resolveBranchesAtOnce) { - do { - resolveGoto(); - - } while (unresolvedGoto.size() != 0); - } else { - resolveGoto(); - - } - if (!DBT_Options.resolveProceduresBeforeBranches) { - resolveAllDynamicJumpTargets(); - } - } while (((unresolvedGoto.size() == 0) - && areDynamicJumpsReadyToResolve()) == false); + if (!DBT_Options.resolveDirectBranchesFirst) { + resolveAllDynamicBranchTargets(); + } + //Resolve all open direct first + resolveAllDirectBranches(); + + if (DBT_Options.resolveDirectBranchesFirst) { + resolveAllDynamicBranchTargets(); + } + // Resolve unresolved dynamic jumps - resolveDynamicJumps(); + resolveDynamicBranches(); // Finish up the trace finishTrace(); @@ -265,13 +257,13 @@ */ private void translateSubTrace(Laziness lazy, int pc) { currentPC = pc; - if (suitableToStop()) { + if (shallTraceStop()) { // Record mapping of this pc value and laziness to this block registerMapping(pc, lazy, currentBlock); // Create next block nextBlock = createBlockAfterCurrent(); // Finish block to return and exit - setReturnValueResolveLazinessAndBranchToFinish(lazy, + appendTraceExit(lazy, new OPT_IntConstantOperand(pc)); // Move currentBlock along currentBlock = nextBlock; @@ -279,6 +271,7 @@ do { if (DBT.VerifyAssertions) DBT._assert(currentBlock.getNumberOfRealInstructions() == 0); + // Record mapping of this pc value and laziness to this block registerMapping(pc, lazy, currentBlock); @@ -292,14 +285,14 @@ // Move currentBlock along currentBlock = nextBlock; currentPC = pc; + if (DBT.VerifyAssertions) DBT._assert(currentBlock.getNumberOfRealInstructions() == 0); // Are we translating in single instruction mode if (DBT_Options.singleInstrTranslation == true) { if (pc != -1) { - setReturnValueResolveLazinessAndBranchToFinish(lazy, - new OPT_IntConstantOperand(pc)); + appendTraceExit(lazy, new OPT_IntConstantOperand(pc)); } break; @@ -377,16 +370,22 @@ gc.cfg.linkInCodeOrder(currentBlock, newBlock); gc.cfg.linkInCodeOrder(newBlock, nxtBlock); - if (DBT.VerifyAssertions) - DBT._assert(currentBlock.isOut(nxtBlock)); + /*if (DBT.VerifyAssertions) + DBT._assert(currentBlock.isOut(nxtBlock));*/ - currentBlock.deleteOut(nxtBlock); - currentBlock.insertOut(newBlock); - newBlock.insertOut(nxtBlock); + if (currentBlock.isOut(nxtBlock)) { + currentBlock.deleteOut(nxtBlock); + currentBlock.insertOut(newBlock); + newBlock.insertOut(nxtBlock); + } + else { + currentBlock.insertOut(newBlock); + } if (DBT_Options.debugCFG) { report(String.format("Created block (%s) after current (%s).", newBlock, currentBlock)); } + return newBlock; } @@ -527,88 +526,69 @@ * @param branchType * The type of branch that best describes this jump. */ - public void appendGoto(int targetPC, Laziness targetLaziness, BranchType branchType) { + public void appendBranch(int targetPC, Laziness targetLaziness, BranchType branchType) { - //see if we already compiled the target address - OPT_BasicBlock target = findMapping(targetPC, targetLaziness); + //Place a GOTO instruction at this point. However, this instruction + //serves more as a placeholder and might be mutated later on. + OPT_Instruction jump = Goto.create(GOTO, null); + appendInstruction(jump); + UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction(jump, (Laziness)targetLaziness.clone(), targetPC, branchType); + unresolvedDirectBranches.add(unresolvedJump); - //if yes, just jump directly to it - if (target != null) { + //Notify the branch profile about certain types of branches + switch (branchType) { + case CALL: + ps.branchInfo.registerCall(currentPC, targetPC); + return; - if (DBT_Options.debugBranchResolution) - System.out.println(String.format("Found precompiled mapping for pc 0x%x: %s", targetPC, target)); - - OPT_Instruction jump = Goto.create(GOTO, target.makeJumpTarget()); - getCurrentBlock().insertOut(target); - appendInstruction(jump); - } - else { - //otherwise, we have to decide whether to compile that address into the trace or to compile - //it as a separate trace. We use the branchType hint for that... - - switch (branchType) { - case CALL: - //exit the trace on a call - ps.branchInfo.registerCall(currentPC, targetPC); - setReturnValueResolveLazinessAndBranchToFinish(targetLaziness, new OPT_IntConstantOperand(targetPC)); - break; - - case RETURN: - //exit the trace - ps.branchInfo.registerReturn(currentPC, targetPC); - setReturnValueResolveLazinessAndBranchToFinish(targetLaziness, new OPT_IntConstantOperand(targetPC)); - break; + case RETURN: + ps.branchInfo.registerReturn(currentPC, targetPC); + return; - default: - //compile the jump directly into the trace. - OPT_Instruction jump = Goto.create(GOTO, null); - UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction(jump, (Laziness)targetLaziness.clone(), targetPC); - unresolvedGoto.add(unresolvedJump); - } + default: + return; } - - } - /** Resolve a single goto instruction */ - private void resolveGoto() { + /** Resolve all unresolved direct branch instructions. */ + private void resolveAllDirectBranches() { - if (unresolvedGoto.size() == 0) - return; + for (int i = 0; i < unresolvedDirectBranches.size(); i++) { - //Get the jump that we're supposed to resolve - UnresolvedJumpInstruction unresolvedInstr = unresolvedGoto.remove(unresolvedGoto.size() - 1); - int targetPc = unresolvedInstr.pc; - Laziness lazyStateAtJump = unresolvedInstr.lazyStateAtJump; - OPT_Instruction gotoInstr = unresolvedInstr.instruction; - - if (DBT.VerifyAssertions) DBT._assert(Goto.conforms(gotoInstr)); - - OPT_BasicBlock targetBB = resolveJumpTarget(targetPc, lazyStateAtJump); - - if (DBT_Options.debugBranchResolution) { - report("Resolving goto " + lazyStateAtJump.makeKey(targetPc) + " " + targetBB); + //Get the jump that we're supposed to resolve + UnresolvedJumpInstruction unresolvedInstr = unresolvedDirectBranches.remove(unresolvedDirectBranches.size() - 1); + int targetPc = unresolvedInstr.pc; + Laziness lazyStateAtJump = unresolvedInstr.lazyStateAtJump; + OPT_Instruction gotoInstr = unresolvedInstr.instruction; + + if (DBT.VerifyAssertions) DBT._assert(Goto.conforms(gotoInstr)); + + OPT_BasicBlock targetBB = resolveBranchTarget(targetPc, lazyStateAtJump, unresolvedInstr.type); + + if (DBT_Options.debugBranchResolution) { + report("Resolving goto " + lazyStateAtJump.makeKey(targetPc) + " " + targetBB); + } + + // Fix up instruction + Goto.setTarget(gotoInstr, targetBB.makeJumpTarget()); + gotoInstr.getBasicBlock().insertOut(targetBB); + + if (DBT_Options.debugBranchResolution) { + report("Properly resolving goto in block " + + gotoInstr.getBasicBlock() + " to " + lazyStateAtJump.makeKey(targetPc) + " " + + targetBB); + } } - - // Fix up instruction - Goto.setTarget(gotoInstr, targetBB.makeJumpTarget()); - gotoInstr.getBasicBlock().insertOut(targetBB); - - if (DBT.VerifyAssertions) DBT._assert(gotoInstr.getBasicBlock().getNumberOfNormalOut() == 1); - - if (DBT_Options.debugBranchResolution) { - report("Properly resolving goto in block " - + gotoInstr.getBasicBlock() + " to " + lazyStateAtJump.makeKey(targetPc) + " " - + targetBB); - } } /** - * Resolves a jump target to an actual basic block. This method usually tries to compile the trace - * for any target addresses that have not yet been compiled. However, when - * {@link DBT_Options#singleInstrTranslation} is turned on, then this method will end the curren trace, - * just returning the address of the next instruction. + * Resolves a branch target to an actual basic block. In case the jump target is not yet part + * of this trace, this method also takes a decision about whether the target shall be translated + * into the trace. * + * Notice that, when {@link DBT_Options#singleInstrTranslation} is turned on, + * this method will always end the current trace, just returning the address of the next instruction. + * * @param targetPc * The address of the target basic block that. * @param lazyStateAtJump @@ -617,28 +597,42 @@ * A basic block that is equivalent to the program counter address <code>targetPc</code> in the * original binary. */ - private OPT_BasicBlock resolveJumpTarget(int targetPc, Laziness lazyStateAtJump) { + private OPT_BasicBlock resolveBranchTarget(int targetPc, Laziness lazyStateAtJump, BranchType branchtype) { //Resolve the address of the target block - OPT_BasicBlock targetBB; - if (DBT_Options.singleInstrTranslation == true) { - //In Single instruction mode, the target block just ends the trace + OPT_BasicBlock targetBB = findMapping(targetPc, lazyStateAtJump); + + //If the target is already part of this trace, then just use the precompiled target + if (targetBB != null) + return targetBB; + + /* The target Block is not yet translated. + * We do not want to translate it into the current trace if + * a) DBT_Options.singleInstrTranslation is enabled + * b) The jump target has already been compiled as a separate method within the code cache + * c) The trace is already too long + * d) the branch is supposedly a CALL or RETURN + */ + if (DBT_Options.singleInstrTranslation == true || + ps.codeCache.tryGet(targetPc) != null || + shallTraceStop() || + branchtype == BranchType.CALL || + branchtype == BranchType.RETURN) { + + //Just exit the trace and continue at the target address in a new trace if (currentBlock.getNumberOfRealInstructions() != 0) { currentBlock = createBlockAfterCurrentNotInCFG(); - System.out.println("Resolving branch to next block."); + + if (DBT_Options.debugBranchResolution) System.out.println("Resolving branch to next block."); } targetBB = currentBlock; - setReturnValueResolveLazinessAndBranchToFinish(lazyStateAtJump, new OPT_IntConstantOperand(targetPc)); - } + appendTraceExit(lazyStateAtJump, new OPT_IntConstantOperand(targetPc)); + registerMapping(targetPc, lazyStateAtJump, targetBB); + } else { - //Try to find if block has now been translated + //Otherwise we will translate the jump into the trace + translateSubTrace((Laziness) lazyStateAtJump.clone(), targetPc); targetBB = findMapping(targetPc, lazyStateAtJump); - - if (targetBB == null) { - // Block not translated so translate - translateSubTrace((Laziness) lazyStateAtJump.clone(), targetPc); - targetBB = findMapping(targetPc, lazyStateAtJump); - } } if (DBT.VerifyAssertions) DBT._assert(targetBB != null); @@ -647,26 +641,23 @@ } /** - * Resolves all dynamic jumps that have been added with - * {@link #appendDynamicJump(OPT_RegisterOperand, Laziness, BranchType)}. + * Resolves all dynamic branches that have been added with + * {@link #appendBranch(OPT_RegisterOperand, Laziness, BranchType)}. */ - private void resolveDynamicJumps() { + private void resolveDynamicBranches() { - for (int i = 0; i < unresolvedDynamicJumps.size(); i++) { + for (int i = 0; i < unresolvedDynamicBranches.size(); i++) { - UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicJumps.get(i); - - Laziness lazy = unresolvedSwitch.lazyStateAtJump; - OPT_Instruction lookupswitch = unresolvedSwitch.instruction; + UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicBranches.get(i); Set<Integer> branchDests = getLikelyJumpTargets(unresolvedSwitch.pc); - resolveSingleDynamicJump(lazy, lookupswitch, branchDests); + resolveSingleDynamicJump(unresolvedSwitch, branchDests); } } /** * Resolves a single dynamic jump that has previously been created with - * {@link #appendDynamicJump(OPT_RegisterOperand, Laziness, BranchType)}. + * {@link #appendBranch(OPT_RegisterOperand, Laziness, BranchType)}. * * @param lazy * The lazy state of the jump that is to be resolved. @@ -675,7 +666,11 @@ * @param destinations * A list of known destinations that this dynamic jumps branches to. */ - private void resolveSingleDynamicJump(Laziness lazy, OPT_Instruction lookupswitch, Set<Integer> destinations) throws Error { + private void resolveSingleDynamicJump(UnresolvedJumpInstruction unresolvedJump, Set<Integer> destinations) throws Error { + + if (DBT.VerifyAssertions) DBT._assert(LookupSwitch.conforms(unresolvedJump.instruction)); + + OPT_Instruction lookupswitch = unresolvedJump.instruction; OPT_BranchOperand default_target = LookupSwitch.getDefault(lookupswitch); OPT_Operand value = LookupSwitch.getValue(lookupswitch); @@ -691,28 +686,19 @@ int match_no = 0; for (int dest_pc : destinations) { - OPT_BasicBlock target = findMapping(dest_pc, lazy); - if (target == null) { - throw new Error("Failed to find trace for " + dest_pc - + " with laziness " + lazy); - } - LookupSwitch.setMatch(lookupswitch, match_no, - new OPT_IntConstantOperand(dest_pc)); - LookupSwitch.setTarget(lookupswitch, match_no, target - .makeJumpTarget()); - LookupSwitch.setBranchProfile(lookupswitch, match_no, - new OPT_BranchProfileOperand(branchProb)); + OPT_BasicBlock target = resolveBranchTarget(dest_pc, unresolvedJump.lazyStateAtJump, unresolvedJump.type); + + LookupSwitch.setMatch(lookupswitch, match_no, new OPT_IntConstantOperand(dest_pc)); + LookupSwitch.setTarget(lookupswitch, match_no, target .makeJumpTarget()); + LookupSwitch.setBranchProfile(lookupswitch, match_no, new OPT_BranchProfileOperand(branchProb)); lookupswitch.getBasicBlock().insertOut(target); match_no++; } } else { int dest_pc = destinations.iterator().next(); - OPT_BasicBlock target = findMapping(dest_pc, lazy); - if (target == null) { - throw new Error("Failed to find trace for " + dest_pc - + " with laziness " + lazy); - } + OPT_BasicBlock target = resolveBranchTarget(dest_pc, unresolvedJump.lazyStateAtJump, unresolvedJump.type); + IfCmp.mutate(lookupswitch, INT_IFCMP, null, value, new OPT_IntConstantOperand(dest_pc), OPT_ConditionOperand.EQUAL(), target.makeJumpTarget(), @@ -725,7 +711,6 @@ } } - /** * Append a dynamic jump (a jump whose target address is not known at translation time) to the * current basic block. @@ -737,100 +722,71 @@ * @param branchType * The type of jump. */ - public void appendDynamicJump(OPT_RegisterOperand targetAddress, Laziness lazyStateAtJump, BranchType branchType) { + public void appendBranch(OPT_RegisterOperand targetAddress, Laziness lazyStateAtJump, BranchType branchType) { OPT_BasicBlock fallThrough = createBlockAfterCurrent(); OPT_Instruction switchInstr; switchInstr = LookupSwitch.create(LOOKUPSWITCH, targetAddress, null, null, fallThrough.makeJumpTarget(), null, 0); appendInstruction(switchInstr); - UnresolvedJumpInstruction unresolvedInfo = new UnresolvedJumpInstruction(switchInstr, (Laziness)lazyStateAtJump.clone(), currentPC); - unresolvedDynamicJumps.add(unresolvedInfo); + UnresolvedJumpInstruction unresolvedInfo = new UnresolvedJumpInstruction(switchInstr, (Laziness)lazyStateAtJump.clone(), currentPC, branchType); + unresolvedDynamicBranches.add(unresolvedInfo); setCurrentBlock(fallThrough); appendRecordUncaughtBranch(currentPC, targetAddress.copyRO(), branchType); - setReturnValueResolveLazinessAndBranchToFinish((Laziness) lazyStateAtJump.clone(), targetAddress.copyRO()); + appendTraceExit((Laziness) lazyStateAtJump.clone(), targetAddress.copyRO()); } /** - * Checks if all dynamic jumps are ready to be resolved (because their target blocks have - * been resolved). - * - * @return - * True if all dynamic jumps can be resolved, false otherwise. - */ - private boolean areDynamicJumpsReadyToResolve() { - for (int i = 0; i < unresolvedDynamicJumps.size(); i++) { - - UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicJumps.get(i); - Laziness lazy = unresolvedSwitch.lazyStateAtJump; - Set<Integer> branchDests = getLikelyJumpTargets(unresolvedSwitch.pc); - - if (branchDests != null) { - for (int dest_pc : branchDests) { - if (findMapping(dest_pc, lazy) == null) { - return false; - } - } - } - } - return true; - } - - /** * Resolves all dynamic jump targets by making sure the respective basic blocks exist. */ - private void resolveAllDynamicJumpTargets() { - for (int i = 0; i < unresolvedDynamicJumps.size(); i++) { + private void resolveAllDynamicBranchTargets() { + for (int i = 0; i < unresolvedDynamicBranches.size(); i++) { - UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicJumps.get(i); + UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicBranches.get(i); Laziness lazy = unresolvedSwitch.lazyStateAtJump; Set<Integer> branchDests = getLikelyJumpTargets(unresolvedSwitch.pc); + if (branchDests != null) { for (int dest_pc : branchDests) { - if (findMapping(dest_pc, lazy) == null) { - // Block not translated so translate - translateSubTrace((Laziness) lazy.clone(), dest_pc); - } + resolveBranchTarget(dest_pc, lazy, unresolvedSwitch.type); } } } } - - /** * Set the return value in the currentBlock, resolve its lazy state (so the * state is no longer lazy) and then set it to branch to the finish block * - * @param value + * @param nextPc * return value for translated code (the PC value of the next * instruction to translate) */ - public void setReturnValueResolveLazinessAndBranchToFinish(Laziness laziness, - OPT_Operand value) { + public void appendTraceExit(Laziness laziness, OPT_Operand nextPc) { - nextBlock = createBlockAfterCurrent(); + //nextBlock = createBlockAfterCurrentNotInCFG(); + // Copy the value into the register specified by gc.resultReg. - appendInstruction(Move.create(INT_MOVE, - new OPT_RegisterOperand(gc.resultReg, VM_TypeReference.Int), value)); + appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand(gc.resultReg, VM_TypeReference.Int), nextPc)); resolveLaziness(laziness); - appendInstruction(Goto.create(GOTO, finishBlock - .makeJumpTarget())); + appendInstruction(Goto.create(GOTO, finishBlock.makeJumpTarget())); currentBlock.deleteNormalOut(); currentBlock.insertOut(finishBlock); if (DBT.VerifyAssertions) DBT._assert(currentBlock.getNumberOfNormalOut() == 1); - currentBlock = nextBlock; + + //currentBlock = nextBlock; } /** - * Is it suitable to stop the trace now? + * Should the trace be stopped as soon as possible? This function can be used to steer how large a single + * trace may be. Return true if the target size for the trace is about to be or has been exceeded. * * @return true => try to stop the trace */ - protected boolean suitableToStop() { + protected boolean shallTraceStop() { if (DBT_Options.singleInstrTranslation && (numberOfInstructions >= 1)) { return true; } else { @@ -880,7 +836,7 @@ * @return whether the trace should continue */ public boolean traceContinuesAfterBranchAndLink(int pc) { - return suitableToStop() == false; + return shallTraceStop() == false; } /** @@ -1015,7 +971,7 @@ appendInstruction(t); - setReturnValueResolveLazinessAndBranchToFinish(lazy, + appendTraceExit(lazy, new OPT_IntConstantOperand(0xEBADC0DE)); } @@ -1312,6 +1268,37 @@ while (block != null && count-- > 0); } + /** + * Appends an call instruction the current trace. + * + * @param callInstruction + * The call instruction that shall be added to the current block. + */ + public void appendCustomCall(OPT_Instruction callInstruction) { + if (DBT.VerifyAssertions) DBT._assert(Call.conforms(callInstruction)); + + OPT_MethodOperand methOp = Call.getMethod(callInstruction); + VM_MethodReference methodRef = methOp.getMemberRef().asMethodReference(); + int callType; + + if (methOp.isVirtual()) + callType = VM_BytecodeConstants.JBC_invokespecial; + else + if (methOp.isInterface()) + callType = VM_BytecodeConstants.JBC_invokeinterface; + else + if (methOp.isSpecial()) + callType = VM_BytecodeConstants.JBC_invokespecial; + else + throw new RuntimeException("Unknown call type in call to appendCustomCall()."); + + trace.registerDynamicLink(methodRef, callType); + + //append the instruction to the current block + callInstruction.position = gc.inlineSequence; + appendInstruction(callInstruction); + } + /** Report some debug output */ protected abstract void report(String str); Added: src/org/binarytranslator/generic/decoder/CodeCache.java =================================================================== --- src/org/binarytranslator/generic/decoder/CodeCache.java (rev 0) +++ src/org/binarytranslator/generic/decoder/CodeCache.java 2007-05-18 17:13:21 UTC (rev 123) @@ -0,0 +1,39 @@ +package org.binarytranslator.generic.decoder; + +import java.util.WeakHashMap; + +import org.binarytranslator.vmInterface.DBT_Trace; + +/** Caches traces and the PC - addresses that they start from. */ +public class CodeCache { + + /** Stores the cached traces. The address at which the trace starts is used as the key. */ + private WeakHashMap<Integer, DBT_Trace> codeSnippets = new WeakHashMap<Integer, DBT_Trace>(); + + /** + * Adds a trace to the codecache. + * @param pc + * The address at which the trace starts. + * @param trace + * The cached trace. + */ + public void add(int pc, DBT_Trace trace) { + + if (codeSnippets.containsKey(pc)) + throw new RuntimeException("The codecache already contains a translation for 0x" + Integer.toHexString(pc)); + + codeSnippets.put(pc, trace); + } + + /** + * Try to retrieve a cached version of a trace starting at <code>pc</code>. + * @param pc + * The address at which the sought trace starts. + * @return + * A trace that starts at <code>pc</code> or null if the cache does not contain + * such a trace. + */ + public DBT_Trace tryGet(int pc) { + return codeSnippets.get(pc); + } +} Modified: src/org/binarytranslator/generic/execution/DynamicTranslationController.java =================================================================== --- src/org/binarytranslator/generic/execution/DynamicTranslationController.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/generic/execution/DynamicTranslationController.java 2007-05-18 17:13:21 UTC (rev 123) @@ -1,7 +1,5 @@ package org.binarytranslator.generic.execution; -import java.util.Hashtable; - import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -16,13 +14,8 @@ */ public class DynamicTranslationController extends ExecutionController { - /** Caches pre-translated code and uses the starting address of the code on the subject machine as a key*/ - private final Hashtable<Integer, DBT_Trace> codeHash; - public DynamicTranslationController(ProcessSpace ps) { super(ps); - - codeHash = new Hashtable<Integer, DBT_Trace>(); } @Override @@ -51,7 +44,7 @@ * An executable VM_CodeArray, which contains a trace starting at the given address. */ private VM_CodeArray getCodeForPC(int pc) { - DBT_Trace trace = codeHash.get(pc); + DBT_Trace trace = ps.codeCache.tryGet(pc); if (trace == null) { trace = translateCode(pc); @@ -81,9 +74,9 @@ // compile the given trace trace.compile(); - // store the compiled code in code hash - codeHash.put(trace.pc, trace); - + // store the compiled code in the code cache + ps.codeCache.add(pc, trace); + return trace; } } Modified: src/org/binarytranslator/generic/memory/CallBasedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-05-18 17:13:21 UTC (rev 123) @@ -9,6 +9,7 @@ package org.binarytranslator.generic.memory; import org.binarytranslator.DBT; +import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.decoder.AbstractCodeTranslator; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DBT_Trace; @@ -118,39 +119,42 @@ */ protected CallBasedMemory(Class memoryClass) { //Debug initializations to run this stuff on SUN - /*memoryType = null; - loadS8 = loadU8 = loadS16 = loadU16 = load32 = null; - store8 = store16 = store32 = null;*/ - + if (DBT_Options.buildForSunVM) { + memoryType = null; + loadS8 = loadU8 = loadS16 = loadU16 = load32 = null; + store8 = store16 = store32 = null; + } + else { memoryType = VM_TypeReference.findOrCreate(memoryClass); - VM_Atom storeDescriptor = VM_Atom.findOrCreateAsciiAtom("(II)V"); - store8 = VM_MemberReference.findOrCreate(memoryType, - VM_Atom.findOrCreateAsciiAtom("store8"), storeDescriptor) - .asMethodReference().resolve(); - store16 = VM_MemberReference.findOrCreate(memoryType, - VM_Atom.findOrCreateAsciiAtom("store16"), storeDescriptor) - .asMethodReference().resolve(); - store32 = VM_MemberReference.findOrCreate(memoryType, - VM_Atom.findOrCreateAsciiAtom("store32"), storeDescriptor) - .asMethodReference().resolve(); + VM_Atom storeDescriptor = VM_Atom.findOrCreateAsciiAtom("(II)V"); + store8 = VM_MemberReference.findOrCreate(memoryType, + VM_Atom.findOrCreateAsciiAtom("store8"), storeDescriptor) + .asMethodReference().resolve(); + store16 = VM_MemberReference.findOrCreate(memoryType, + VM_Atom.findOrCreateAsciiAtom("store16"), storeDescriptor) + .asMethodReference().resolve(); + store32 = VM_MemberReference.findOrCreate(memoryType, + VM_Atom.findOrCreateAsciiAtom("store32"), storeDescriptor) + .asMethodReference().resolve(); - VM_Atom loadDescriptor = VM_Atom.findOrCreateAsciiAtom("(I)I"); - loadS8 = VM_MemberReference.findOrCreate(mem... [truncated message content] |