From: <mic...@us...> - 2007-07-09 10:36:57
|
Revision: 149 http://svn.sourceforge.net/pearcolator/?rev=149&view=rev Author: michael_baer Date: 2007-07-09 03:36:57 -0700 (Mon, 09 Jul 2007) Log Message: ----------- Refactorings in org.binarytranslator.generic.decoder: - Renamed classes - Cleaned up interfaces Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/arm/os/process/loader/ARM_RuntimeLinker.java src/org/binarytranslator/arch/ppc/decoder/PPC2IR.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/decoder/X86_ModRM_Decoder.java src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java src/org/binarytranslator/generic/execution/InterpreterController.java src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java src/org/binarytranslator/generic/memory/CallBasedMemory.java src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java src/org/binarytranslator/generic/memory/Memory.java src/org/binarytranslator/generic/os/process/ProcessSpace.java src/org/binarytranslator/vmInterface/DBT_Trace.java Added Paths: ----------- src/org/binarytranslator/arch/x86/decoder/X86_AbstractInstructionDecoder.java src/org/binarytranslator/generic/decoder/CodeTranslator.java Removed Paths: ------------- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java src/org/binarytranslator/generic/decoder/DisassembledInstruction.java src/org/binarytranslator/generic/decoder/InstructionDecoder.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-07-09 10:36:57 UTC (rev 149) @@ -6,7 +6,7 @@ import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode; -import org.binarytranslator.generic.decoder.AbstractCodeTranslator; +import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.vmInterface.DBT_Trace; import org.jikesrvm.classloader.VM_Atom; @@ -17,7 +17,7 @@ import org.jikesrvm.classloader.VM_TypeReference; import org.jikesrvm.compilers.opt.ir.*; -public class ARM2IR extends AbstractCodeTranslator implements OPT_HIRGenerator { +public class ARM2IR extends CodeTranslator implements OPT_HIRGenerator { /** Mapping of ARM registers to HIR registers */ private OPT_Register regMap[] = new OPT_Register[16]; Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-07-09 10:36:57 UTC (rev 149) @@ -21,6 +21,7 @@ import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction.Condition; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.generic.decoder.DisassembledInstruction; +import org.binarytranslator.generic.decoder.Disassembler; /** * This class transfers an ARM instruction into a human-readable assembly @@ -41,7 +42,7 @@ * The process space from which the instruction is read. * @return A disassembled ARM instruction. */ - public final static DisassembledInstruction disassemble(int address, + public final static Disassembler.Instruction disassemble(int address, ARM_ProcessSpace ps) { Instruction decodedInstruction; @@ -70,7 +71,7 @@ * The instruction that is to be decoded. * @return A human-readable version of the given instruction. */ - final static DisassembledInstruction disassemble( + final static Disassembler.Instruction disassemble( ARM_Instructions.Instruction instruction) { DisassemblingVisitor disassembler = new DisassemblingVisitor(); @@ -81,7 +82,7 @@ /** Represents a disassembled ARM instruction. */ private final static class ARM_DisassembledInstruction implements - DisassembledInstruction { + Disassembler.Instruction { /** A readable version of the diassembled instruction. */ private final String instruction; @@ -129,7 +130,7 @@ ARM_InstructionVisitor { /** This field receives the disassembled instruction. */ - private ARM_DisassembledInstruction result; + private Disassembler.Instruction result; private DisassemblingVisitor() { } Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-07-09 10:36:57 UTC (rev 149) @@ -7,13 +7,13 @@ import org.binarytranslator.arch.arm.decoder.ARM_Interpreter; 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.CodeTranslator; import org.binarytranslator.generic.decoder.Interpreter; import org.binarytranslator.generic.memory.ByteAddressedMemory; 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; public abstract class ARM_ProcessSpace extends ProcessSpace { @@ -49,7 +49,7 @@ * the generation context for the HIR generation * @return a HIR generator */ - public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context, DBT_Trace trace) { + public CodeTranslator createTranslator(OPT_GenerationContext context, DBT_Trace trace) { return new ARM2IR(context, trace); } @@ -73,7 +73,7 @@ } @Override - public Interpreter createInstructionInterpreter() throws UnsupportedOperationException { + public Interpreter createInterpreter() throws UnsupportedOperationException { return new ARM_Interpreter(this); } Modified: src/org/binarytranslator/arch/arm/os/process/loader/ARM_RuntimeLinker.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/loader/ARM_RuntimeLinker.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/arm/os/process/loader/ARM_RuntimeLinker.java 2007-07-09 10:36:57 UTC (rev 149) @@ -111,7 +111,7 @@ int pc = startPC; ps.setCurrentInstructionAddress(startPC); - Interpreter interpreter = ps.createInstructionInterpreter(); + Interpreter interpreter = ps.createInterpreter(); ((ARM_ProcessSpace)ps).registers.set(ARM_Registers.LR, startPC); Modified: src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-07-09 10:36:57 UTC (rev 149) @@ -14,7 +14,7 @@ import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.ppc.os.process.PPC_ProcessSpace; -import org.binarytranslator.generic.decoder.AbstractCodeTranslator; +import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; import org.binarytranslator.vmInterface.DBT_Trace; @@ -42,7 +42,7 @@ * * @author Richard Matley, Ian Rogers */ -public final class PPC2IR extends AbstractCodeTranslator implements OPT_HIRGenerator, +public final class PPC2IR extends CodeTranslator implements OPT_HIRGenerator, OPT_Operators, OPT_Constants { // -oO Caches of references to process space entities Oo- Modified: src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-07-09 10:36:57 UTC (rev 149) @@ -14,6 +14,7 @@ import org.binarytranslator.arch.ppc.decoder.PPC2IR; import org.binarytranslator.arch.ppc.decoder.PPC_InstructionDecoder; import org.binarytranslator.arch.ppc.os.process.linux.PPC_LinuxProcessSpace; +import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.execution.GdbController.GdbTarget; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.generic.memory.ByteAddressedByteSwapMemory; @@ -22,7 +23,6 @@ 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; import org.vmmagic.pragma.Uninterruptible; @@ -140,7 +140,7 @@ * the generation context for the HIR generation * @return a HIR generator */ - public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context, DBT_Trace trace) { + public CodeTranslator createTranslator(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-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-07-09 10:36:57 UTC (rev 149) @@ -13,7 +13,7 @@ import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; import org.binarytranslator.arch.x86.os.process.X86_Registers; -import org.binarytranslator.generic.decoder.AbstractCodeTranslator; +import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; import org.binarytranslator.vmInterface.DBT_Trace; @@ -25,7 +25,7 @@ import org.jikesrvm.compilers.opt.OPT_Constants; import org.jikesrvm.compilers.opt.ir.*; -public class X862IR extends AbstractCodeTranslator implements OPT_HIRGenerator, +public class X862IR extends CodeTranslator implements OPT_HIRGenerator, OPT_Operators, OPT_Constants { private static final VM_TypeReference psTref; Added: src/org/binarytranslator/arch/x86/decoder/X86_AbstractInstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_AbstractInstructionDecoder.java (rev 0) +++ src/org/binarytranslator/arch/x86/decoder/X86_AbstractInstructionDecoder.java 2007-07-09 10:36:57 UTC (rev 149) @@ -0,0 +1,59 @@ +/* + * This file is part of binarytranslator.org. The binarytranslator.org + * project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 + */ +package org.binarytranslator.arch.x86.decoder; + +import org.binarytranslator.generic.os.process.ProcessSpace; +import org.binarytranslator.generic.decoder.CodeTranslator; +import org.binarytranslator.generic.fault.BadInstructionException; + +/** + * A decoder is a class capable of translating, interpretting or disassembling + * an instruction + */ +public abstract class X86_AbstractInstructionDecoder { + /** + * Translate a single instruction + * + * @param translationHelper + * the object containing the translation sequence + * @param ps + * the process space of the translation + * @param pc + * the address of the instruction to translate + * @return the address of the next instruction or -1 if this instruction has + * branched to the end of the trace + */ + public int translate(CodeTranslator translationHelper, ProcessSpace ps, + Object lazy, int pc) { + throw new Error("TODO"); + } + + /** + * Interpret a single instruction + * + * @param ps + * the process space of the interpretation, contains the fetched + * instruction and instruction address + * @return the next instruction interpreter + */ + public X86_AbstractInstructionDecoder interpret(ProcessSpace ps) + throws BadInstructionException { + throw new Error("TODO"); + } + + /** + * Disassemble an instruction + * + * @param ps + */ + public String disassemble(ProcessSpace ps) { + // In general this isn't complete + throw new Error("Disassembly not yet complete"); + } +} Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-07-09 10:36:57 UTC (rev 149) @@ -12,7 +12,6 @@ import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; import org.binarytranslator.arch.x86.os.process.X86_Registers; import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; -import org.binarytranslator.generic.decoder.InstructionDecoder; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; @@ -22,7 +21,7 @@ /** * Decoder for X86 instructions */ -public class X86_InstructionDecoder extends InstructionDecoder { +public class X86_InstructionDecoder extends X86_AbstractInstructionDecoder { /* * Process defaults @@ -711,7 +710,7 @@ * instruction and instruction address * @return the next instruction interpreter */ - public InstructionDecoder interpret(ProcessSpace ps, int pc) + public X86_AbstractInstructionDecoder interpret(ProcessSpace ps, int pc) throws BadInstructionException { X86_InstructionDecoder decoder = getDecoder(ps, pc); System.err.println("Attempt to interpret " + decoder.disassemble(ps, pc)); Modified: src/org/binarytranslator/arch/x86/decoder/X86_ModRM_Decoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_ModRM_Decoder.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/x86/decoder/X86_ModRM_Decoder.java 2007-07-09 10:36:57 UTC (rev 149) @@ -10,7 +10,7 @@ import org.binarytranslator.arch.x86.os.process.X86_Registers; -import org.binarytranslator.generic.decoder.AbstractCodeTranslator; +import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.decoder.Laziness; /** @@ -386,7 +386,7 @@ * Get the RM field as a decoded operand, the RM field encodes either a * register or memory location */ - X86_DecodedOperand getRM(AbstractCodeTranslator translationHelper, Laziness lazy, + X86_DecodedOperand getRM(CodeTranslator translationHelper, Laziness lazy, X86_SIB_Decoder sib, int displacement, int operandSize, int addressSize, int segment) { if (addressSize == 32) { Modified: src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-07-09 10:36:57 UTC (rev 149) @@ -12,11 +12,11 @@ import java.util.Hashtable; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; -import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.generic.memory.ByteAddressedMemory; +import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.execution.GdbController.GdbTarget; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.arch.x86.os.process.linux.X86_LinuxProcessSpace; @@ -149,7 +149,7 @@ * @param context the generation context for the HIR generation * @return a HIR generator */ - public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context, DBT_Trace trace) { + public CodeTranslator createTranslator(OPT_GenerationContext context, DBT_Trace trace) { return new X862IR(context, trace); } Deleted: src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-07-09 10:36:57 UTC (rev 149) @@ -1,1479 +0,0 @@ -/* - * This file is part of binarytranslator.org. The binarytranslator.org - * project is distributed under the Common Public License (CPL). - * A copy of the license is included in the distribution, and is also - * available at http://www.opensource.org/licenses/cpl1.0.php - * - * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 - */ -package org.binarytranslator.generic.decoder; - -import java.util.Enumeration; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -import org.binarytranslator.DBT; -import org.binarytranslator.DBT_Options; -import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; -import org.binarytranslator.generic.decoder.Laziness.Key; -import org.binarytranslator.generic.fault.BadInstructionException; -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; -import org.jikesrvm.classloader.VM_MethodReference; -import org.jikesrvm.classloader.VM_TypeReference; -import org.jikesrvm.compilers.opt.OPT_Constants; -import org.jikesrvm.compilers.opt.ir.Athrow; -import org.jikesrvm.compilers.opt.ir.BBend; -import org.jikesrvm.compilers.opt.ir.Call; -import org.jikesrvm.compilers.opt.ir.Goto; -import org.jikesrvm.compilers.opt.ir.IfCmp; -import org.jikesrvm.compilers.opt.ir.IfCmp2; -import org.jikesrvm.compilers.opt.ir.LookupSwitch; -import org.jikesrvm.compilers.opt.ir.Move; -import org.jikesrvm.compilers.opt.ir.New; -import org.jikesrvm.compilers.opt.ir.OPT_AddressConstantOperand; -import org.jikesrvm.compilers.opt.ir.OPT_BasicBlock; -import org.jikesrvm.compilers.opt.ir.OPT_BranchOperand; -import org.jikesrvm.compilers.opt.ir.OPT_BranchProfileOperand; -import org.jikesrvm.compilers.opt.ir.OPT_ConditionOperand; -import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; -import org.jikesrvm.compilers.opt.ir.OPT_Instruction; -import org.jikesrvm.compilers.opt.ir.OPT_IntConstantOperand; -import org.jikesrvm.compilers.opt.ir.OPT_MethodOperand; -import org.jikesrvm.compilers.opt.ir.OPT_Operand; -import org.jikesrvm.compilers.opt.ir.OPT_Operator; -import org.jikesrvm.compilers.opt.ir.OPT_Operators; -import org.jikesrvm.compilers.opt.ir.OPT_Register; -import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperand; -import org.jikesrvm.compilers.opt.ir.OPT_TrueGuardOperand; -import org.jikesrvm.compilers.opt.ir.OPT_TypeOperand; - -/** - * A collection of common tools used by decoders. The public entry point for the - * translators is generateHIR(OPT_GenerationContext gc). - * - * <dl> - * <dt>Description of the translation algorithm</dt> - * <dd> - * <ol> - * <li>The translation is set up so that the start and end blocks are created. - * The start block branches to a prefill block that loads all the register - * values</li> - * <li>Translation starts from the PC value given in the DBT_Trace.</li> - * <li>Translation translates subject instructions to HIR using the - * translateInstruction method. This and the derived decoder object contain the - * utilities required to aid an instruction translation.</li> - * <li>The trace ends when the branch prediction deems it necessary. The - * closing basic blocks are generated and things are wrapped up.</li> - * </ol> - * </dd> - * </dl> - */ -public abstract class AbstractCodeTranslator implements OPT_Constants, - OPT_Operators { - - /** 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 */ - public static final VM_Method sysCallMethod; - - /** VM_TypeReference of org.binarytranslator.generic.fault.BadInstructionException */ - public static final VM_Class badInstrKlass; - - /** Method BadInstructionException.<init> */ - public static final VM_Method badInstrKlassInitMethod; - - /** Method ProcessSpace.recordUncaughtBranchBadInstructionException.<init> */ - public static final VM_Method recordUncaughtBranchMethod; - - static { - psTref = VM_TypeReference.findOrCreate(ProcessSpace.class); - VM_MethodReference sysCallMethRef = (VM_MethodReference) VM_MemberReference - .findOrCreate(psTref, VM_Atom.findOrCreateAsciiAtom("doSysCall"), - VM_Atom.findOrCreateAsciiAtom("()V")); - sysCallMethod = sysCallMethRef.resolveInvokeSpecial(); - - badInstrKlass = VM_TypeReference.findOrCreate(BadInstructionException.class).resolve().asClass(); - - VM_MethodReference badInstrKlassInitMethRef = (VM_MethodReference) VM_MemberReference - .findOrCreate( - badInstrKlass.getTypeRef(), - VM_Atom.findOrCreateAsciiAtom("<init>"), - VM_Atom - .findOrCreateAsciiAtom("(ILorg/binarytranslator/generic/os/process/ProcessSpace;)V")); - badInstrKlassInitMethod = badInstrKlassInitMethRef.resolveInvokeSpecial(); - - VM_MethodReference recordUncaughtBranchMethRef = (VM_MethodReference) VM_MemberReference - .findOrCreate(psTref, VM_Atom - .findOrCreateAsciiAtom("recordUncaughtBranch"), VM_Atom - .findOrCreateAsciiAtom("(IIII)V")); - recordUncaughtBranchMethod = recordUncaughtBranchMethRef - .resolveInvokeSpecial(); - } - - /** Number of translated instructions */ - private int numberOfInstructions; - - /** The process space object used by the running binary. */ - public final ProcessSpace ps; - - /** The VM method's generation context. */ - protected OPT_GenerationContext gc; - - /** The OPT_BasicBlock in which instructions are currently being inserted */ - protected OPT_BasicBlock currentBlock; - - /** The pc value corresponding to the instruction currently being translated */ - protected int currentPC; - - /** The pc value of the first instruction in the trace */ - protected int startingPC; - - /** The OPT_BasicBlock which will contain the next translated instruction */ - protected OPT_BasicBlock nextBlock; - - /** - * The basic block is used by finish trace to hold all the code that must be - * executed before returning to the main run loop - */ - protected OPT_BasicBlock finishBlock; - - /** - * This block gets instructions to pre-fill registers inserted into it. - */ - protected OPT_BasicBlock preFillBlock; - - /** - * This variable is being set by a call to {@link #printTraceAfterCompletion()} and notifies - * the system that the current trace shall be printed, after it has been completed. */ - private boolean requestPrintTrace; - - /** Map to locate HIR basic blocks to re-use translation within a trace */ - protected final HashMap<Laziness.Key, OPT_BasicBlock> blockMap; - - /** This class stores information about a jump instruction within the current trace, whose - * target has not yet been resolved. */ - private final static class UnresolvedJumpInstruction { - - /** A reference to the jump instruction within the code. This is either a GOTO or SWITCH instruction. */ - public final OPT_Instruction instruction; - - /** The lazy state at the jump location. */ - public final Laziness lazyStateAtJump; - - /** Stores the target of the jump instruction or -1, if this value is unknown. */ - public final int targetPC; - - /** Stores the address, at which the jump occurs*/ - public final int pc; - - /** Identifies the type of branch. */ - public final BranchType type; - - public UnresolvedJumpInstruction(OPT_Instruction instruction, - Laziness lazyStateAtJump, int pc, int targetPC, BranchType type) { - this.instruction = instruction; - this.lazyStateAtJump = lazyStateAtJump; - this.pc = pc; - this.type = type; - this.targetPC = targetPC; - } - } - - /** - * List of unresolved direct branches. The destinations of direct branches are - * already known at translation time. */ - private final List<UnresolvedJumpInstruction> unresolvedDirectBranches; - - /** - * List of unresolved dynamic branches. Dynamics branches have a destination - * address that is only determined at runtime. */ - private final List<UnresolvedJumpInstruction> unresolvedDynamicBranches; - - /** - * Constructor - * - * @param context - * The JRVM generation context for this trace. - */ - 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; - currentPC = ((DBT_Trace) (gc.method)).pc; - startingPC = currentPC; - - // Number of translated instructions - numberOfInstructions = 0; - - // Create map of (PC & laziness) -> OPT_BasicBlock - blockMap = new HashMap<Key, OPT_BasicBlock>(); - - // Create preFillBlock, currentBlock and finishBlock - gc.prologue.insertOut(gc.epilogue); - preFillBlock = createBlockAfter(gc.prologue); - currentBlock = createBlockAfter(preFillBlock); - finishBlock = createBlockAfterCurrent(); - - // Fix up stores - unresolvedDirectBranches = new LinkedList<UnresolvedJumpInstruction>(); - unresolvedDynamicBranches = new LinkedList<UnresolvedJumpInstruction>(); - } - - /** Returns the number of previously translated instructions within this trace. */ - public int getNumInstructions() { - return numberOfInstructions; - } - - /** - * Deriving classes may call this method if they want to print the current trace after all - * dependencies (unknown branch targets etc.) have been resolved. This function is useful for - * debug purposes. - */ - protected void printTraceAfterCompletion() { - requestPrintTrace = true; - } - - /** This is the main loop, which generates the HIR. */ - public void generateHIR() { - // Load all the register values to be used in a trace - preFillAllRegisters(); - - // Translate from the current program counter - translateSubTrace(createInitialLaziness(), currentPC); - - // Translating the subtrace finished so resolve any unresolved branches - - while (unresolvedDirectBranches.size() > 0 || unresolvedDynamicBranches.size() > 0) { - // Resolve all open direct branches first - resolveAllDirectBranches(); - - // Resolve unresolved dynamic jumps - resolveAllDynamicBranches(); - } - - // Finish up the trace - finishTrace(); - - if (DBT_Options.eliminateRegisterFills) { - eliminateRegisterFills(getUnusedRegisters()); - } - - if (requestPrintTrace) { - requestPrintTrace = false; - printNextBlocks(preFillBlock, 50); - } - - // TODO: maximizeBasicBlocks() - } - - /** - * Translate a sequence of instructions upto an instruction that doesn't know - * its immediate/default successor. The currentBlock should be an empty basic - * block. - */ - private void translateSubTrace(Laziness lazy, int pc) { - currentPC = pc; - - 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 - appendTraceExit(lazy, new OPT_IntConstantOperand(pc)); - // Move currentBlock along - currentBlock = nextBlock; - } else { - do { - if (DBT.VerifyAssertions) - DBT._assert(currentBlock.getNumberOfRealInstructions() == 0); - - // Record mapping of this pc value and laziness to this block - registerMapping(pc, lazy, currentBlock); - - // Create next block - nextBlock = createBlockAfterCurrent(); - - // Translare instruction and get address of next instruction - pc = translateInstruction(lazy, pc); - numberOfInstructions++; - - // 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) { - appendTraceExit(lazy, new OPT_IntConstantOperand(pc)); - } - - break; - } - - // Do we already have a translation for this next block? - OPT_BasicBlock possibleNextBlock = findMapping(pc, lazy); - if (possibleNextBlock != null) { - // Yes, branch to that and stop translating - appendInstruction(Goto.create(GOTO, possibleNextBlock - .makeJumpTarget())); - OPT_BasicBlock gotoBlock = currentBlock; - currentBlock = createBlockAfterCurrent(); - gotoBlock.deleteNormalOut(); - gotoBlock.insertOut(possibleNextBlock); - if (DBT.VerifyAssertions) - DBT._assert(gotoBlock.getNumberOfNormalOut() == 1); - break; - } - } while (pc != -1); - } - } - - /** - * Get the block which is currently having instructions inserted into it - * - * @return the current block - */ - public OPT_BasicBlock getCurrentBlock() { - return currentBlock; - } - - /** - * Get the block which will contain the translation of the next PPC - * instruction - * - * @return the next block - */ - public OPT_BasicBlock getNextBlock() { - return nextBlock; - } - - /** - * Set the block which is currently having instructions inserted into it - * - * @param newCurrentBlock - * the new current basic block - */ - public void setCurrentBlock(OPT_BasicBlock newCurrentBlock) { - currentBlock = newCurrentBlock; - } - - /** - * Set the block which will contain the translation of the next PPC - * instruction - * - * @param newCurrentBlock - * the new next basic block - */ - public void setNextBlock(OPT_BasicBlock newNextBlock) { - nextBlock = newNextBlock; - } - - /** - * Create a basic block immediately after the current block and link its edges - * into the CFG and code ordering - * - * @return the new basic block - */ - public OPT_BasicBlock createBlockAfterCurrent() { - OPT_BasicBlock nxtBlock = currentBlock.nextBasicBlockInCodeOrder(); - OPT_BasicBlock newBlock = new OPT_BasicBlock(0, gc.inlineSequence, gc.cfg); - - gc.cfg.breakCodeOrder(currentBlock, nxtBlock); - gc.cfg.linkInCodeOrder(currentBlock, newBlock); - gc.cfg.linkInCodeOrder(newBlock, nxtBlock); - - /* - * if (DBT.VerifyAssertions) DBT._assert(currentBlock.isOut(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; - } - - /** - * Create a basic block immediately after the current block and link its edges - * into code ordering but not the CFG - * - * @return the new basic block - */ - public OPT_BasicBlock createBlockAfterCurrentNotInCFG() { - OPT_BasicBlock nxtBlock = currentBlock.nextBasicBlockInCodeOrder(); - OPT_BasicBlock newBlock = new OPT_BasicBlock(0, gc.inlineSequence, gc.cfg); - - gc.cfg.breakCodeOrder(currentBlock, nxtBlock); - gc.cfg.linkInCodeOrder(currentBlock, newBlock); - gc.cfg.linkInCodeOrder(newBlock, nxtBlock); - - if (DBT_Options.debugCFG) { - report(String.format("Created non-cfg block (%s) after current (%s).", - newBlock, currentBlock)); - } - return newBlock; - } - - /** - * Create a basic block immediately after the given block and link its edges - * into the CFG and code ordering - * - * @param afterBlock - * The block after which the new block is to be created. - * @return the new basic block - */ - public OPT_BasicBlock createBlockAfter(OPT_BasicBlock afterBlock) { - OPT_BasicBlock nxtBlock = afterBlock.nextBasicBlockInCodeOrder(); - OPT_BasicBlock newBlock = new OPT_BasicBlock(0, gc.inlineSequence, gc.cfg); - - gc.cfg.breakCodeOrder(afterBlock, nxtBlock); - gc.cfg.linkInCodeOrder(afterBlock, newBlock); - gc.cfg.linkInCodeOrder(newBlock, nxtBlock); - - if (DBT.VerifyAssertions) - DBT._assert(afterBlock.isOut(nxtBlock)); - afterBlock.deleteOut(nxtBlock); - afterBlock.insertOut(newBlock); - newBlock.insertOut(nxtBlock); - - if (DBT_Options.debugCFG) { - report(String.format("Created block (%s) after current (%s).", newBlock, - afterBlock)); - } - - return newBlock; - } - - /** - * Append a HIR instruction to the current basic block - * - * @param i - * The instruciton that is to be appended to the current bloc. - */ - public void appendInstruction(OPT_Instruction i) { - if (i.bcIndex == UNKNOWN_BCI) { - i.position = gc.inlineSequence; - // we only have 16bits to distinguish instructions (the bcIndex - // is effective 16bit when stored in the machine code map), - // Intel can't distinguish branches within 16bytes, so neither - // can we, the top bit is saved for distinguished addresses we - // need to know to dynamically link things - i.bcIndex = ((currentPC - startingPC) >> 4) & 0x7FFF; - } - currentBlock.appendInstruction(i); - } - - /** - * Generate a branch profile operand for the current instruction - * - * @param likely - * Does this branch have a likely hint? - */ - public OPT_BranchProfileOperand getConditionalBranchProfileOperand( - boolean likely) { - return gc.getConditionalBranchProfileOperand( - ((currentPC - startingPC) >> 4) & 0x7FFF, likely); - } - - /** - * We're finished translating this trace so .. 1) put all the registers back - * into the process space 2) return the new PC value - */ - protected void finishTrace() { - // finishBlock is already linked into the cfg, we just need to - // make sure we are adding to it. - currentBlock = finishBlock; - spillAllRegisters(); - } - - /** - * Get the generation context. - */ - public OPT_GenerationContext getGenerationContext() { - return gc; - } - - /** - * Register a mapping between a pc and lazy and a hir block - * - * @param pc - * The program counter whose translation the basic bock represents. - * @param lazy - * The lazy state that is assumed for this basic block. - * @param hirBlock - * The block that is to be registered. - */ - protected void registerMapping(int pc, Laziness lazy, OPT_BasicBlock hirBlock) { - blockMap.put(lazy.makeKey(pc), hirBlock); - } - - /** - * Find if there's already a translation for a given pc and laziness - * - * @param pc - * The program counter address at which the returned basic block - * shall start. - * @param lazy - * The lazy state assumed within the returned trace. - * @return An appropriate basic block or null if no translation exists. - */ - protected OPT_BasicBlock findMapping(int pc, Laziness lazy) { - return blockMap.get(lazy.makeKey(pc)); - } - - /** - * Create a HIR Goto instruction that jumps to the address - * <code>targetPc</code>. There's a caveat on using this that there are no - * other out edges for this BB. - * - * @param targetPC - * The address where we shall jump to. - * @param targetLaziness - * The current at the point of jump. - */ - public void appendBranch(int targetPC, Laziness targetLaziness) { - - appendStaticBranch(Goto.create(GOTO, null), targetPC, targetLaziness, BranchType.DIRECT_BRANCH, -1); - } - - /** - * Appends the conditional branch instruction <code>conditional</code> that jumps to the address - * <code>targetPc</code> to the current block. - * - * @param targetPC - * The address where we shall jump to. - * @param targetLaziness - * The current at the point of jump. - */ - public void appendConditionalBranch(OPT_Instruction conditional, int targetPC, Laziness targetLaziness) { - - if (DBT.VerifyAssertions) DBT._assert(IfCmp.conforms(conditional) || IfCmp2.conforms(conditional)); - appendStaticBranch(conditional, targetPC, targetLaziness, BranchType.DIRECT_BRANCH, -1); - } - - /** - * Create a HIR Goto instruction that jumps to the address - * <code>targetPc</code>. There's a caveat on using this that there are no - * other out edges for this BB. - * - * @param targetPC - * The address where we shall jump to. - * @param targetLaziness - * The current at the point of jump. - * @param branchType - * The type of branch that best describes this jump. - */ - public void appendCall(int targetPC, Laziness targetLaziness, int retAddr) { - - appendStaticBranch(Goto.create(GOTO, null), targetPC, targetLaziness, BranchType.CALL, retAddr); - } - - private void appendStaticBranch(OPT_Instruction branch, int targetPC, Laziness targetLaziness, BranchType branchType, int retAddr) { - // Place a GOTO instruction at this point. However, this instruction - // serves more as a placeholder and might be mutated later on. - appendInstruction(branch); - UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction( - branch, (Laziness) targetLaziness.clone(), currentPC, targetPC, BranchType.CALL); - unresolvedDirectBranches.add(unresolvedJump); - - if (branchType == BranchType.CALL) - ps.branchInfo.registerCall(currentPC, targetPC, retAddr); - else - if (branchType == BranchType.RETURN) - ps.branchInfo.registerReturn(currentPC, targetPC); - else - ps.branchInfo.registerBranch(currentPC, targetPC, branchType); - } - - /** - * Append a dynamic jump (a jump whose target address is not known at translation time) to the - * current basic block. - * - * @param targetAddress - * The target address of the jump. - * @param lazyStateAtJump - * The lazy state at the point the jump was added. - * @param retAddr - * The address, to which the function call will (most likely) return. - */ - public void appendCall(OPT_RegisterOperand targetAddress, Laziness lazyStateAtJump, int retAddr) { - - appendDynamicBranch(targetAddress, lazyStateAtJump, BranchType.CALL, retAddr); - } - - /** - * Append a dynamic jump (a jump whose target address is not known at translation time) to the - * current basic block. - * - * @param targetAddress - * The target address of the jump. - * @param lazyStateAtJump - * The lazy state at the point the jump was added. - * @param branchType - * The type of jump. - */ - public void appendBranch(OPT_RegisterOperand targetAddress, Laziness lazyStateAtJump, BranchType branchType) { - - if (DBT.VerifyAssertions && branchType == BranchType.CALL) throw new RuntimeException("Use the more specific appendCall to create dynamic calls."); - - appendDynamicBranch(targetAddress, lazyStateAtJump, branchType, -1); - } - - /** - * Append a dynamic jump (a jump whose target address is not known at translation time) to the - * current basic block. - * - * @param targetAddress - * The target address of the jump. - * @param lazyStateAtJump - * The lazy state at the point the jump was added. - * @param branchType - * The type of jump. - * @param retAddr - * The address, to which the function call will (most likely) return or an arbitrary value, if - * branchType is not BranchType.CALL. - */ - private void appendDynamicBranch(OPT_RegisterOperand targetAddress, Laziness lazyStateAtJump, BranchType branchType, int retAddr) { - - OPT_BasicBlock fallThrough = createBlockAfterCurrent(); - OPT_Instruction switchInstr; - switchInstr = LookupSwitch.create(LOOKUPSWITCH, targetAddress.copyRO(), null, null, fallThrough.makeJumpTarget(), null, 0); - appendInstruction(switchInstr); - - UnresolvedJumpInstruction unresolvedInfo = new UnresolvedJumpInstruction(switchInstr, (Laziness)lazyStateAtJump.clone(), currentPC, -1, branchType); - unresolvedDynamicBranches.add(unresolvedInfo); - - setCurrentBlock(fallThrough); - appendRecordUncaughtBranch(currentPC, targetAddress.copyRO(), branchType, retAddr); - appendTraceExit((Laziness) lazyStateAtJump.clone(), targetAddress); - - } - - /** Resolve all unresolved direct branch instructions. */ - private void resolveAllDirectBranches() { - - while (unresolvedDirectBranches.size() > 0) { - - // Get the jump that we're supposed to resolve - UnresolvedJumpInstruction unresolvedInstr = unresolvedDirectBranches.remove(0); - int targetPc = unresolvedInstr.targetPC; - Laziness lazyStateAtJump = unresolvedInstr.lazyStateAtJump; - OPT_Instruction gotoInstr = unresolvedInstr.instruction; - OPT_BasicBlock targetBB = resolveBranchTarget(targetPc, unresolvedInstr); - - if (DBT_Options.debugBranchResolution) { - report("Resolved goto in block " + gotoInstr.getBasicBlock() - + " to " + lazyStateAtJump.makeKey(targetPc) + " " + targetBB); - } - - // Fix up instruction - setBranchTarget(gotoInstr, targetBB.makeJumpTarget()); - gotoInstr.getBasicBlock().insertOut(targetBB); - } - } - - /** - * Sets the target of the branching instruction <code>branch</code> to <code>target</code>. - * @param branch - * A branching instruction. Either a Goto or - * @param target - * The jump target. - */ - private void setBranchTarget(OPT_Instruction branch, OPT_BranchOperand target) { - if (Goto.conforms(branch)) { - Goto.setTarget(branch, target); - } - else if (IfCmp.conforms(branch)) { - IfCmp.setTarget(branch, target); - } - else if (IfCmp2.conforms(branch)) { - IfCmp2.setTarget1(branch, target); - } - } - - /** - * This function is being called to decide whether a branch to <code>targetPc</code> (caused by the - * jump instruction <code>jump</code>) shall be inlined into the trace. This function is only called when - * the jump target is not part of the current trace anyway. - * - * This function may be overriden to fine-tune whether certain branches shall be inlined or not. - * - * @param targetPc - * The address that we're jumping to. - * @param jump - * Detailled information describing the jump. - * @return - * True to make the system inline the target of this branch, false otherwise. - */ - protected boolean inlineBranchInstruction(int targetPc, UnresolvedJumpInstruction jump) { - /* - * The target Block is not yet translated. We do not want to inline 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 - */ - return DBT_Options.singleInstrTranslation == false - && ps.codeCache.tryGet(targetPc) == null && !shallTraceStop() - && jump.type != BranchType.CALL && jump.type != BranchType.RETURN; - } - - /** - * 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 jump - * The branch instruction that we are trying to resolve. - * @return A basic block that is equivalent to the program counter address - * <code>targetPc</code> in the original binary. - */ - private OPT_BasicBlock resolveBranchTarget(int targetPc, UnresolvedJumpInstruction jump) { - // Resolve the address of the target block - OPT_BasicBlock targetBB = findMapping(targetPc, jump.lazyStateAtJump); - - // If the target is already part of this trace, then just use the - // precompiled target - if (targetBB != null) - return targetBB; - - if (inlineBranchInstruction(targetPc, jump)) { - - // Just exit the trace and continue at the target address in a new trace - if (currentBlock.getNumberOfRealInstructions() != 0) { - currentBlock = createBlockAfterCurrentNotInCFG(); - - if (DBT_Options.debugBranchResolution) - System.out.println("Resolving branch to next block."); - } - - targetBB = currentBlock; - appendTraceExit(jump.lazyStateAtJump, new OPT_IntConstantOperand(targetPc)); - registerMapping(targetPc, jump.lazyStateAtJump, targetBB); - } else { - // Otherwise we will translate the jump into the trace - translateSubTrace((Laziness) jump.lazyStateAtJump.clone(), targetPc); - targetBB = findMapping(targetPc, jump.lazyStateAtJump); - } - - if (DBT.VerifyAssertions) - DBT._assert(targetBB != null); - - return targetBB; - } - - /** - * Resolves all dynamic branches that have been added with - * {@link #appendBranch(OPT_RegisterOperand, Laziness, BranchType)}. - */ - private void resolveAllDynamicBranches() { - - while (unresolvedDynamicBranches.size() > 0) { - - UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicBranches.remove(0); - Set<Integer> branchDests = getLikelyJumpTargets(unresolvedSwitch.pc); - - resolveSingleDynamicJump(unresolvedSwitch, branchDests); - } - } - - /** - * Resolves a single dynamic jump that has previously been created with - * {@link #appendBranch(OPT_RegisterOperand, Laziness, BranchType)}. - * - * @param lazy - * The lazy state of the jump that is to be resolved. - * @param lookupswitch - * Each dynamic jump is converted to a switch statement. This is the - * switch statement for the current jump. - * @param destinations - * A list of known destinations that this dynamic jumps branches to. - */ - 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); - - if (destinations != null && destinations.size() > 0) { - if ((destinations.size() > 1) - || (lookupswitch.getBasicBlock().nextBasicBlockInCodeOrder() != default_target.target - .getBasicBlock())) { - float branchProb = (1.0f - OPT_BranchProfileOperand.UNLIKELY) - / (float) destinations.size(); - LookupSwitch.mutate(lookupswitch, LOOKUPSWITCH, value, null, null, - default_target, OPT_BranchProfileOperand.unlikely(), destinations - .size() * 3); - int match_no = 0; - for (int dest_pc : destinations) { - - OPT_BasicBlock target = resolveBranchTarget(dest_pc, unresolvedJump); - - 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 = resolveBranchTarget(dest_pc, unresolvedJump); - - IfCmp.mutate(lookupswitch, INT_IFCMP, null, value, - new OPT_IntConstantOperand(dest_pc), OPT_ConditionOperand.EQUAL(), - target.makeJumpTarget(), OPT_BranchProfileOperand.likely()); - lookupswitch.getBasicBlock().insertOut(target); - } - } else { - //we don't yet know where this jump will go, so just do nothing, which will exit the trace - } - } - - /** - * 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 nextPc - * return value for translated code (the PC value of the next - * instruction to translate) - */ - public void appendTraceExit(Laziness laziness, OPT_Operand nextPc) { - - // Copy the value into the register specified by gc.resultReg. - appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand( - gc.resultReg, VM_TypeReference.Int), nextPc.copy())); - resolveLaziness(laziness); - appendInstruction(Goto.create(GOTO, finishBlock.makeJumpTarget())); - currentBlock.deleteNormalOut(); - currentBlock.insertOut(finishBlock); - if (DBT.VerifyAssertions) - DBT._assert(currentBlock.getNumberOfNormalOut() == 1); - } - - /** - * 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 shallTraceStop() { - if (DBT_Options.singleInstrTranslation && (numberOfInstructions >= 1)) { - return true; - } - - switch (gc.options.getOptLevel()) { - case 0: - return numberOfInstructions > DBT_Options.instrOpt0; - case 1: - return numberOfInstructions > DBT_Options.instrOpt1; - default: - return numberOfInstructions > DBT_Options.instrOpt2; - } - } - - /** - * Register a branch and link instruction - * - * @param pc - * the address of the branch instruction - * @param ret - * the address returned to - * @param dest - * the destination of the branch instruction - */ - public void registerBranchAndLink(int pc, int ret, int dest) { - ps.branchInfo.registerCall(pc, ret, dest); - } - - /** - * Returns a vector of likely branch targets for the branch at address - * <code>pc</code>. - * - * @param pc - * The location at which the branch occurs. - * @return A set of likely destinations for that jump. - */ - private Set<Integer> getLikelyJumpTargets(int pc) { - return ps.branchInfo.getKnownBranchTargets(pc); - } - - /** - * Should a trace follow a branch and link instruction or should it terminate - * the trace? - * - * @param pc - * the address of the branch and link instruction - * @return whether the trace should continue - */ - public boolean traceContinuesAfterBranchAndLink(int pc) { - return shallTraceStop() == false; - } - - /** - * Load all the registers from the ProcessSpace into the pre-fill block - */ - private void preFillAllRegisters() { - OPT_BasicBlock temp = currentBlock; - currentBlock = preFillBlock; - fillAllRegisters(); - ps.memory.initTranslate(this); // Set up memory - currentBlock = temp; - } - - /** - * Eliminate unnecessary register spill and fill code - ie a register wasn't - * used so eliminate references to it - */ - protected void eliminateRegisterFills(OPT_Register unusedRegisters[]) { - if (unusedRegisters.length > 0) { - OPT_BasicBlock curBB = gc.prologue; - while (curBB != null) { - OPT_Instruction curInstr = curBB.firstInstruction(); - loop_over_instructions: while (BBend.conforms(curInstr) == false) { - for (Enumeration du = curInstr.getRootOperands(); du - .hasMoreElements();) { - OPT_Operand curOp = (OPT_Operand) du.nextElement(); - if (curOp.isRegister()) { - OPT_Register curReg = curOp.asRegister().register; - for (int i = 0; i < unusedRegisters.length; i++) { - if (unusedRegisters[i] == curReg) { - OPT_Instruction toRemove = curInstr; - curInstr = curInstr.nextInstructionInCodeOrder(); - toRemove.remove(); - continue loop_over_instructions; - } - } - } - } - curInstr = curInstr.nextInstructionInCodeOrder(); - } - curBB = curBB.nextBasicBlockInCodeOrder(); - } - } - } - - /** - * Appends a system call to the current basic block. - * - * @param lazy - * current translation laziness - * @param pc - * address of system call instruction - */ - public void appendSystemCall(Laziness lazy) { - // We need to make sure that all registers contain their latest values, - // before performing the actual system call. - resolveLaziness(lazy); - spillAllRegisters(); - - // Plant call - OPT_Instruction s = Call.create(CALL, null, null, null, null, 1); - - OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(sysCallMethod - .getMemberRef().asMethodReference(), sysCallMethod); - - OPT_Operand psRef = gc.makeLocal(1, psTref); - Call.setParam(s, 0, psRef); // Reference to ps, sets 'this' pointer for - // doSysCall - Call.setGuard(s, new OPT_TrueGuardOperand()); - Call.setMethod(s, methOp); - Call.setAddress(s, - new OPT_AddressConstantOperand(sysCallMethod.getOffset())); - s.position = gc.inlineSequence; - s.bcIndex = DBT_Trace.DO_SYSCALL; - appendInstruction(s); - - // Fill all registers again following system call - fillAllRegisters(); - } - - /** - * Plant a throw of a bad instruction exception - * - * @param lazy - * current translation laziness - * @param pc - * the program counter of the bad instruction - */ - public void appendThrowBadInstruction(Laziness lazy, int pc) { - // We need to make sure that all registers contain their latest values, - // before - // throwing the bad instruction exception. - resolveLaziness(lazy); - spillAllRegisters(); - - OPT_Operator newOperator; - OPT_TypeOperand typeOperand = new OPT_TypeOperand(badInstrKlass); - VM_TypeReference eTref = badInstrKlass.getTypeRef(); - - if (badInstrKlass.isInitialized() || badInstrKlass.isInBootImage()) { - newOperator = NEW; - } else { - newOperator = NEW_UNRESOLVED; - } - - OPT_RegisterOperand eRef = gc.temps.makeTemp(eTref); - OPT_Instruction n = New.create(newOperator, eRef, typeOperand); - n.position = gc.inlineSequence; - n.bcIndex = DBT_Trace.BAD_INSTRUCTION_NEW; - appendInstruction(n); - - OPT_Operand psRef = gc.makeLocal(1, psTref); - OPT_Instruction c = Call.create(CALL, null, null, null, null, 3); - OPT_MethodOperand methOp = OPT_MethodOperand.SPECIAL( - badInstrKlassInitMethod.getMemberRef().asMethodReference(), - badInstrKlassInitMethod); - Call.setParam(c, 0, eRef.copy()); // 'this' pointer in - // BadInstructionException.init - Call.setParam(c, 1, new OPT_IntConstantOperand(pc)); - Call.setParam(c, 2, psRef); - Call.setGuard(c, new OPT_TrueGuardOperand()); - Call.setMethod(c, methOp); - Call.setAddress(c, new OPT_AddressConstantOperand(badInstrKlassInitMethod - .getOffset())); - c.position = gc.inlineSequence; - c.bcIndex = DBT_Trace.BAD_INSTRUCTION_INIT; - - appendInstruction(c); - - OPT_Instruction t = Athrow.create(ATHROW, eRef.copyRO()); - t.position = gc.inlineSequence; - t.bcIndex = DBT_Trace.BAD_INSTRUCTION_THROW; - - appendInstruction(t); - - appendTraceExit(lazy, new OPT_IntConstantOperand(0xEBADC0DE)); - } - - /** - * Plant a record uncaught branch call. NB register state won't get resolved - * for call - * - * @param pc - * the address of the branch instruction - * @param destination - * the register operand holding the destination - * @param branchType - * The type of the uncaught branch - * @param retAddr - * An optional return address, in case the branch is a call. Otherwise, this value is ignored. - */ - private void appendRecordUncaughtBranch(int pc, OPT_RegisterOperand destination, BranchType branchType, int retAddr) { - // Is it sensible to record this information? - if ((gc.options.getOptLevel() > 0) - && (DBT_Options.plantUncaughtBranchWatcher)) { - // Plant call - OPT_Instruction s = Call.create(CALL, null, null, null, null, 5); - OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL( - recordUncaughtBranchMethod.getMemberRef().asMethodReference(), - recordUncaughtBranchMethod); - OPT_Operand psRef = gc.makeLocal(1, psTref); - Call.setParam(s, 0, psRef); // Reference to ps, sets 'this' pointer - Call.setParam(s, 1, new OPT_IntConstantOperand(pc)); // Address of branch - // instruction - Call.setParam(s, 2, destination.copy()); // Destination of branch value - Call.setParam(s, 3, new OPT_IntConstantOperand(branchType.ordinal())); // Branch type - Call.setParam(s, 4, new OPT_IntConstantOperand(retAddr)); // return address - // value - Call.setGuard(s, new OPT_TrueGuardOperand()); - Call.setMethod(s, methOp); - Call.setAddress(s, new OPT_AddressConstantOperand( - recordUncaughtBranchMethod.getOffset())); - s.position = gc.inlineSequence; - s.bcIndex = DBT_Trace.RECORD_BRANCH; - appendInstruction(s); - } - } - - /** Temporary int variables */ - private OPT_Register intTemps[]; - - /** - * Get/create a temporary int - * - * @param num - * a hint to allow for reuse of temps across instructions - */ - public OPT_RegisterOperand getTempInt(int num) { - if (DBT.VerifyAssertions) DBT._assert(num < 10); - - if (intTemps == null) { - intTemps = new OPT_Register[10]; - } - OPT_Register result = intTemps[num];... [truncated message content] |