From: <mic...@us...> - 2007-05-21 17:43:20
|
Revision: 127 http://svn.sourceforge.net/pearcolator/?rev=127&view=rev Author: michael_baer Date: 2007-05-21 10:43:21 -0700 (Mon, 21 May 2007) Log Message: ----------- - enabled load/storing a branch profile from file - added branch profiling in ARM interpreted code when DBT_Options.profileDuringInterpration is set - slightly changed handling of branch profile creation - Using a HashMap instead of a Weakhashmap in CodeCache to prevent a VM assertion - minor fixes Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/Main.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.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/PPC_InstructionDecoder.java src/org/binarytranslator/generic/branch/BranchLogic.java src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java src/org/binarytranslator/generic/decoder/CodeCache.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java src/org/binarytranslator/generic/os/process/ProcessSpace.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/DBT_Options.java 2007-05-21 17:43:21 UTC (rev 127) @@ -19,16 +19,15 @@ public class DBT_Options { /** Remove features that will only work on jikes? */ - public final static boolean buildForSunVM = true; + public final static boolean buildForSunVM = false; - /** - * Debug binary loading - */ + /** Enable the profiling of application during interpretation? */ + public final static boolean profileDuringInterpretation = true; + + /** Debug binary loading */ public final static boolean debugLoader = true; - /** - * Are unimplemented system calls are fatal? - */ + /** Are unimplemented system calls are fatal? */ public final static boolean unimplementedSystemCallsFatal = false; // -oO Translation settings Oo- @@ -208,6 +207,8 @@ debugRuntime = Boolean.parseBoolean(value); } else if (arg.equalsIgnoreCase("-X:dbt:debugBranchResolution")) { debugBranchResolution = Boolean.parseBoolean(value); + } else if (arg.equalsIgnoreCase("-X:dbt:debugMemory")) { + debugMemory = Boolean.parseBoolean(value); } else if (arg.equalsIgnoreCase("-X:dbt:debugSyscall")) { debugSyscall = Boolean.parseBoolean(value); } else if (arg.equalsIgnoreCase("-X:dbt:debugSyscallMore")) { Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/Main.java 2007-05-21 17:43:21 UTC (rev 127) @@ -9,6 +9,7 @@ package org.binarytranslator; import java.io.File; +import java.io.IOException; import org.binarytranslator.generic.execution.DynamicTranslationController; import org.binarytranslator.generic.execution.ExecutionController; @@ -29,6 +30,8 @@ * */ public class Main { + private static ProcessSpace ps; + /** * Debug information * @@ -49,6 +52,8 @@ System.out .println("org.binarytranslator.Main [-X:dbt:...] <program> <args...>"); } + + /** * Main method @@ -81,8 +86,6 @@ return; } - ProcessSpace ps; - try { report("Loading " + DBT_Options.executableFile); Loader loader = Loader.getLoader(DBT_Options.executableFile); @@ -120,6 +123,16 @@ } controller.run(); - System.out.println("\nProgram has finished."); + System.out.println("\nExecution controller has exited."); } + + public static void onExit(int exitcode) { + System.out.println("\nProgram has finished. Exitcode: " + exitcode); + + try { + ps.branchInfo.saveAsXML("/tmp/profile.xml"); + } catch (IOException e) { + e.printStackTrace(); + } + } } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-21 17:43:21 UTC (rev 127) @@ -1,6 +1,7 @@ package org.binarytranslator.arch.arm.decoder; import org.binarytranslator.DBT; +import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoder.ARM_InstructionFactory; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.OperandWrapper; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.DataProcessing.Opcode; @@ -8,6 +9,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.branch.BranchLogic.BranchType; import org.binarytranslator.generic.decoder.Interpreter; import com.sun.org.apache.bcel.internal.generic.InstructionFactory; @@ -457,7 +459,39 @@ } public abstract void execute(); + + /** + * Stores the result of adding <code>lhs</code> + <code>rhs</code> to <code>Rd</code> + * and sets the flags accordingly, if <code>updateConditionCodes</code> is set. + * @param lhs + * @param rhs + */ + protected final void setAddResult(int lhs, int rhs) { + setFlagsForAdd(lhs, rhs); + if (DBT_Options.profileDuringInterpretation && Rd == 15) { + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), lhs + rhs, BranchType.INDIRECT_BRANCH); + } + + regs.set(Rd, lhs + rhs); + } + + /** + * Stores the result of adding <code>lhs</code> - <code>rhs</code> to <code>Rd</code> + * and sets the flags accordingly, if <code>updateConditionCodes</code> is set. + * @param lhs + * @param rhs + */ + protected final void setSubResult(int lhs, int rhs) { + setFlagsForSub(lhs, rhs); + + if (DBT_Options.profileDuringInterpretation && Rd == 15) { + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), lhs - rhs, BranchType.INDIRECT_BRANCH); + } + + regs.set(Rd, lhs - rhs); + } + /** Sets the processor flags according to the result of adding <code>lhs</code> and <code>rhs</code>.*/ protected final void setFlagsForAdd(int lhs, int rhs) { @@ -522,6 +556,21 @@ return super.resolveOperand2(); } } + + /** Stores the result of a logical operation to a register and, if <code>updateConditionFlags</code> + * is set, also sets the flags accordingly. */ + protected final void setLogicalResult(int result) { + + if (DBT_Options.profileDuringInterpretation && Rd == 15) { + if (getOpcode() == Opcode.MOV && operand2.getType() == OperandWrapper.Type.Register && operand2.getRegister() == ARM_Registers.LR) + ps.branchInfo.registerReturn(regs.get(ARM_Registers.PC), result); + else + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), result, BranchType.INDIRECT_BRANCH); + } + + regs.set(Rd, result); + setFlagsForLogicalOperator(result); + } /** Sets the condition field for logical operations. */ protected final void setFlagsForLogicalOperator(int result) { @@ -546,8 +595,7 @@ @Override public void execute() { int result = resolveOperand1() & resolveOperand2(); - regs.set(Rd, result); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -561,8 +609,7 @@ @Override public void execute() { int result = resolveOperand1() ^ resolveOperand2(); - regs.set(Rd, result); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -576,10 +623,8 @@ public void execute() { int operand1 = resolveOperand1(); int operand2 = resolveOperand2(); - int result = operand1 + operand2; - - regs.set(Rd, result); - setFlagsForAdd(operand1, operand2); + + setAddResult(operand1, operand2); } } @@ -594,10 +639,7 @@ public void execute() { int operand1 = resolveOperand1(); int operand2 = resolveOperand2(); - int result = operand1 - operand2; - - regs.set(Rd, result); - setFlagsForSub(operand1, operand2); + setSubResult(operand1, operand2); } } @@ -612,10 +654,7 @@ public void execute() { int operand1 = resolveOperand1(); int operand2 = resolveOperand2(); - int result = operand2 - operand1; - - regs.set(Rd, result); - setFlagsForSub(operand2, operand1); + setSubResult(operand2, operand1); } } @@ -646,11 +685,8 @@ return; } } - - int result = operand1 + operand2; - - regs.set(Rd, result); - setFlagsForAdd(operand1, operand2); + + setAddResult(operand1, operand2); } } @@ -679,10 +715,7 @@ } } - int result = operand1 - operand2; - - regs.set(Rd, result); - setFlagsForSub(operand1, operand2); + setSubResult(operand1, operand2); } } @@ -770,8 +803,7 @@ @Override public void execute() { int result = resolveOperand1() | resolveOperand2(); - regs.set(Rd, result); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -785,8 +817,7 @@ /** Moves a value into a register .*/ public void execute() { int result = resolveOperand2(); - regs.set(Rd, result); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -802,8 +833,7 @@ /** Clear bits in a register by a mask given by a second operand. */ public void execute() { int result = resolveOperand1() & (~resolveOperand2()); - regs.set(Rd, result); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -818,8 +848,7 @@ @Override public void execute() { int result = ~resolveOperand2(); - regs.set(Rd, result); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -951,6 +980,9 @@ if (transferPC) { nextAddress += 4; int newpc = ps.memory.load32(nextAddress); + + if (DBT_Options.profileDuringInterpretation) + ps.branchInfo.registerReturn(regs.get(ARM_Registers.PC), newpc); if (forceUser) { //when we are transferring the PC with a forced-user transfer, then we also want to @@ -1040,8 +1072,16 @@ public void execute() { //if we're supposed to link, then write the previous address into the link register - if (link) + if (link) { regs.set(ARM_Registers.LR, regs.get(ARM_Registers.PC) + 4); + + if (DBT_Options.profileDuringInterpretation) + ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), regs.get(ARM_Registers.PC) + getOffset() + 8, regs.get(ARM_Registers.PC) + 4); + } + else { + if (DBT_Options.profileDuringInterpretation) + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), regs.get(ARM_Registers.PC) + getOffset() + 8, BranchType.DIRECT_BRANCH); + } } public int getSuccessor(int pc) { @@ -1084,13 +1124,19 @@ + target.getType()); } + //if we're supposed to link, then write the previous address into the link register + if (link) { + regs.set(ARM_Registers.LR, previousAddress - 4); + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), targetAddress, BranchType.CALL); + } + else { + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), targetAddress, BranchType.DIRECT_BRANCH); + } + + //jump to the new address regs.set(ARM_Registers.PC, targetAddress); regs.setThumbMode(thumb); - - //if we're supposed to link, then write the previous address into the link register - if (link) - regs.set(ARM_Registers.LR, previousAddress - 4); } public int getSuccessor(int pc) { @@ -1376,6 +1422,11 @@ //finally, write the variable into a register regs.set(Rd, value); + + if (DBT_Options.profileDuringInterpretation) { + if (Rd == 15) + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), value, BranchType.INDIRECT_BRANCH); + } } else { //we are store a value from a register to memory. Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-21 17:43:21 UTC (rev 127) @@ -1663,7 +1663,10 @@ arm2ir.getCurrentBlock().deleteNormalOut(); } - arm2ir.appendBranch(pc + getOffset() + 8, lazy, link ? BranchType.CALL : BranchType.DIRECT_BRANCH); + if (link) + arm2ir.appendCall(pc + getOffset() + 8, lazy, pc + 4); + else + arm2ir.appendBranch(pc + getOffset() + 8, lazy, BranchType.DIRECT_BRANCH); } public int getSuccessor(int pc) { Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-05-21 17:43:21 UTC (rev 127) @@ -9,7 +9,6 @@ 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; @@ -39,11 +38,7 @@ protected ARM_ProcessSpace() { registers = new ARM_Registers(); - - if (DBT_Options.buildForSunVM) - memory = new DebugMemory(); - else - memory = new ByteAddressedMemory(); + memory = new ByteAddressedMemory(); } /** Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-05-21 17:43:21 UTC (rev 127) @@ -11702,10 +11702,13 @@ plantBranchToBlockDependentOnCondition(ppc2ir, instructionEndBlock, lazy, BI, !branch_if_cond_true, likely_to_fallthrough); } + + if (LK == 0) + ppc2ir.appendBranch(target_address, lazy, BranchType.DIRECT_BRANCH); + else + ppc2ir.appendCall(target_address, lazy, pc + 4); if ((LK == 0) || ppc2ir.traceContinuesAfterBranchAndLink(pc)) { - // Plant branch block - ppc2ir.appendBranch(target_address, lazy, LK != 0 ? BranchType.CALL : BranchType.DIRECT_BRANCH); // stop translation on branch always if (BO == 0x14) { @@ -11731,7 +11734,6 @@ } else { // This was a branch and link and the trace should stop, so end // gracefully - ppc2ir.appendBranch(target_address, lazy, BranchType.CALL); return -1; } } Modified: src/org/binarytranslator/generic/branch/BranchLogic.java =================================================================== --- src/org/binarytranslator/generic/branch/BranchLogic.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/generic/branch/BranchLogic.java 2007-05-21 17:43:21 UTC (rev 127) @@ -8,12 +8,29 @@ */ package org.binarytranslator.generic.branch; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; import java.util.HashSet; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + import org.binarytranslator.DBT; +import org.binarytranslator.DBT_Options; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; /** * Object capturing branches and jumps so that traces can avoid terminating on @@ -72,22 +89,12 @@ procedure = new ProcedureInformation(pc, ret, dest); procedures.put(dest, procedure); } + + registerBranch(pc, dest); } - - /** - * Register a call (branch and link) instruction - * - * @param pc - * the address of the branch instruction - * @param dest - * the destination of the branch instruction - */ - public void registerCall(int pc, int dest) { - registerCall(pc, dest, -1); - } /** - * Register a branch to the link register + * Register a function return. * * @param pc * the address of the branch instruction @@ -95,10 +102,14 @@ * the return address (value of the link register) */ public void registerReturn(int pc, int lr) { + ProcedureInformation procedure = getLikelyProcedure(pc); + if (procedure != null) { procedure.registerReturn(pc, lr); } + + registerBranch(pc, lr); } /** @@ -123,6 +134,7 @@ * Registers a branch from the address <code>origin</code> to the address <code>target</code>. * The type of branch is determined by <code>type</code>, which is an ordinal from the * {@link BranchType} enum. + * * @param origin * The address from which the branch occurs. * @param target @@ -130,24 +142,30 @@ * @param type * The most likely type of the branch. This is taken from the {@link BranchType} enum. */ - public void registerBranch(int origin, int target, int type) { - - if (DBT.VerifyAssertions) DBT._assert(type > 0 && type < BranchType.values().length); - - //Some branch types require a special registration (calls and returns) - switch (BranchType.values()[type]) { - case CALL: - registerCall(origin, target); - break; - - case RETURN: - registerReturn(origin, target); - break; - - default: - break; - } - + public void registerBranch(int origin, int target, BranchType type) { + + switch (type) { + case CALL: + throw new RuntimeException("Use the more specific registerCall() for these cases."); + + case RETURN: + registerReturn(origin, target); + break; + + default: + registerBranch(origin, target); + } + } + + /** + * Appends a recorded branch from <code>origin</code> to <code>target</code> to the branch profile. + * + * @param origin + * The address that the branch is taking place from. + * @param target + * The branch target address. + */ + private void registerBranch(int origin, int target) { //Perform the general branch registration, too Set<Integer> dests = branchSitesAndDestinations.get(origin); @@ -175,4 +193,126 @@ public Set<Integer> getKnownBranchTargets(int pc) { return branchSitesAndDestinations.get(pc); } + + public void loadFromXML(String filename) throws IOException { + + DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); + Document doc; + try { + DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); + doc = docBuilder.parse(filename); + } catch (ParserConfigurationException e) { + throw new RuntimeException("Error creating DocumentBuilder instance to read an XML file."); + } catch (SAXException e) { + throw new IOException("File " + filename + " is not a valid XML file."); + } + + if (DBT.VerifyAssertions) DBT._assert(doc != null); + + Element root = doc.getDocumentElement(); + + if (!root.getNodeName().equals("branch-profile")) + throw new IOException("File is not a valid XML branch profile."); + + Node branches = null; + + for (int i = 0; i < root.getChildNodes().getLength(); i++) { + Node node = root.getChildNodes().item(0); + + if (node.getNodeName().equals("branches")) { + branches = node; + break; + } + } + + if (branches == null) + throw new IOException("File is not a valid XML branch profile."); + + for (int i = 0; i < branches.getChildNodes().getLength(); i++) { + Node siteNode = branches.getChildNodes().item(i); + + if (!siteNode.getNodeName().equals("origin") || siteNode.getNodeType() != Node.ELEMENT_NODE) + throw new IOException("File is not a valid XML branch profile."); + + int pc = Integer.parseInt(((Element)siteNode).getAttribute("address")); + + for (int n = 0; n < siteNode.getChildNodes().getLength(); n++) { + Node target = siteNode.getChildNodes().item(n); + + if (!target.getNodeName().equals("target") || target.getNodeType() != Node.ELEMENT_NODE) + throw new IOException("File is not a valid XML branch profile."); + + int targetAddress = Integer.parseInt(((Element)target).getAttribute("address")); + registerBranch(pc, targetAddress); + } + } + } + + /** + * Saves the branch profile of the current process space to the give file in XML format. + * + * @param filename + * The name of the file to which the branch profile is saved. + * @throws IOException + * Thrown if there is an error while creating the file. + */ + public void saveAsXML(String filename) throws IOException { + + FileOutputStream outputStream; + + try { + File f = new File(filename); + + if (!f.exists()) + f.createNewFile(); + + outputStream = new FileOutputStream(f); + } + catch (FileNotFoundException e) { + //this should not happen, as we just created the file + throw new IOException("Error creating file: " + filename); + } + + //Create an XML representation of the branch profile + DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder; + try { + docBuilder = docBuilderFactory.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw new IOException("Error creating parser to produce XML document."); + } + Document doc = docBuilder.newDocument(); + + Element root = doc.createElement("branch-profile"); + root.setAttribute("application", DBT_Options.executableFile); + doc.appendChild(root); + + Element branchesElement = doc.createElement("branches"); + root.appendChild(branchesElement); + + for (int pc : branchSitesAndDestinations.keySet()) { + Element branchSiteElement = doc.createElement("origin"); + branchesElement.appendChild(branchSiteElement); + branchSiteElement.setAttribute("address", Integer.toString(pc)); + + for (int target : getKnownBranchTargets(pc)) { + Element branchTargetElement = doc.createElement("target"); + branchSiteElement.appendChild(branchTargetElement); + branchTargetElement.setAttribute("address", Integer.toString(target)); + } + } + + //Output the resulting XML document + TransformerFactory tFactory = TransformerFactory.newInstance(); + Transformer transformer; + try { + transformer = tFactory.newTransformer(); + DOMSource source = new DOMSource(doc); + StreamResult result = new StreamResult(outputStream); + transformer.transform(source, result); + + } catch (Exception e) { + e.printStackTrace(); + } + } } Modified: src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-05-21 17:43:21 UTC (rev 127) @@ -74,18 +74,22 @@ * </dd> * </dl> */ -public abstract class AbstractCodeTranslator implements OPT_Constants, OPT_Operators { +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 */ + /** + * VM_TypeReference of + * org.binarytranslator.generic.fault.BadInstructionException + */ public static final VM_Class badInstrKlass; /** Method BadInstructionException.<init> */ @@ -106,15 +110,17 @@ BadInstructionException.class).asClass(); VM_MethodReference badInstrKlassInitMethRef = (VM_MethodReference) VM_MemberReference - .findOrCreate(badInstrKlass.getTypeRef(), + .findOrCreate( + badInstrKlass.getTypeRef(), VM_Atom.findOrCreateAsciiAtom("<init>"), - VM_Atom.findOrCreateAsciiAtom("(ILorg/binarytranslator/generic/os/process/ProcessSpace;)V")); + 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("(III)V")); + .findOrCreateAsciiAtom("(IIII)V")); recordUncaughtBranchMethod = recordUncaughtBranchMethRef .resolveInvokeSpecial(); } @@ -153,14 +159,18 @@ /** Map to locate HIR basic blocks to re-use translation within a trace */ protected final HashMap<Laziness.Key, OPT_BasicBlock> blockMap; - + private final static class UnresolvedJumpInstruction { 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, BranchType type) { + + public UnresolvedJumpInstruction(OPT_Instruction instruction, + Laziness lazyStateAtJump, int pc, BranchType type) { this.instruction = instruction; this.lazyStateAtJump = lazyStateAtJump; this.pc = pc; @@ -168,27 +178,30 @@ } } - /** - * List of unresolved direct branches. The destinations of direct branches are already known at - * translation time.*/ + /** + * 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 branches. Dynamics branches have a destination address that is only - * determined at runtime. */ + + /** + * List of unresolved dynamic branches. Dynamics branches have a destination + * address that is only determined at runtime. + */ private final ArrayList<UnresolvedJumpInstruction> unresolvedDynamicBranches; /** * Constructor * * @param context - * The JRVM generation context for this trace. + * The JRVM generation context for this trace. */ - protected AbstractCodeTranslator(OPT_GenerationContext context, DBT_Trace trace) { - - //Store the trace that we're invoked from + 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; @@ -211,7 +224,7 @@ unresolvedDirectBranches = new ArrayList<UnresolvedJumpInstruction>(); unresolvedDynamicBranches = new ArrayList<UnresolvedJumpInstruction>(); } - + /** Returns the number of previously translated instructions within this trace. */ public int getNumInstructions() { return numberOfInstructions; @@ -230,10 +243,10 @@ if (!DBT_Options.resolveDirectBranchesFirst) { resolveAllDynamicBranchTargets(); } - - //Resolve all open direct first + + // Resolve all open direct first resolveAllDirectBranches(); - + if (DBT_Options.resolveDirectBranchesFirst) { resolveAllDynamicBranchTargets(); } @@ -263,15 +276,14 @@ // Create next block nextBlock = createBlockAfterCurrent(); // Finish block to return and exit - appendTraceExit(lazy, - new OPT_IntConstantOperand(pc)); + 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); @@ -285,7 +297,7 @@ // Move currentBlock along currentBlock = nextBlock; currentPC = pc; - + if (DBT.VerifyAssertions) DBT._assert(currentBlock.getNumberOfRealInstructions() == 0); @@ -370,22 +382,23 @@ 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)); + */ if (currentBlock.isOut(nxtBlock)) { currentBlock.deleteOut(nxtBlock); currentBlock.insertOut(newBlock); newBlock.insertOut(nxtBlock); - } - else { + } else { currentBlock.insertOut(newBlock); } if (DBT_Options.debugCFG) { - report(String.format("Created block (%s) after current (%s).", newBlock, currentBlock)); + report(String.format("Created block (%s) after current (%s).", newBlock, + currentBlock)); } - + return newBlock; } @@ -404,7 +417,8 @@ gc.cfg.linkInCodeOrder(newBlock, nxtBlock); if (DBT_Options.debugCFG) { - report(String.format("Created non-cfg block (%s) after current (%s).", newBlock, currentBlock)); + report(String.format("Created non-cfg block (%s) after current (%s).", + newBlock, currentBlock)); } return newBlock; } @@ -414,7 +428,7 @@ * into the CFG and code ordering * * @param afterBlock - * The block after which the new block is to be created. + * The block after which the new block is to be created. * @return the new basic block */ public OPT_BasicBlock createBlockAfter(OPT_BasicBlock afterBlock) { @@ -432,9 +446,10 @@ newBlock.insertOut(nxtBlock); if (DBT_Options.debugCFG) { - report(String.format("Created block (%s) after current (%s).", newBlock, afterBlock)); + report(String.format("Created block (%s) after current (%s).", newBlock, + afterBlock)); } - + return newBlock; } @@ -442,7 +457,7 @@ * Append a HIR instruction to the current basic block * * @param i - * The instruciton that is to be appended to the current bloc. + * The instruciton that is to be appended to the current bloc. */ public void appendInstruction(OPT_Instruction i) { if (i.bcIndex == UNKNOWN_BCI) { @@ -461,7 +476,7 @@ * Generate a branch profile operand for the current instruction * * @param likely - * Does this branch have a likely hint? + * Does this branch have a likely hint? */ public OPT_BranchProfileOperand getConditionalBranchProfileOperand( boolean likely) { @@ -491,11 +506,11 @@ * Register a mapping between a pc and lazy and a hir block * * @param pc - * The program counter whose translation the basic bock represents. + * The program counter whose translation the basic bock represents. * @param lazy - * The lazy state that is assumed for this basic block. + * The lazy state that is assumed for this basic block. * @param hirBlock - * The block that is to be registered. + * The block that is to be registered. */ protected void registerMapping(int pc, Laziness lazy, OPT_BasicBlock hirBlock) { blockMap.put(lazy.makeKey(pc), hirBlock); @@ -505,175 +520,267 @@ * 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. + * 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. + * 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. + * 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. + * The address where we shall jump to. * @param targetLaziness - * The current at the point of jump. + * The current at the point of jump. * @param branchType - * The type of branch that best describes this jump. + * The type of branch that best describes this jump. */ public void appendBranch(int targetPC, Laziness targetLaziness, BranchType branchType) { - //Place a GOTO instruction at this point. However, this instruction - //serves more as a placeholder and might be mutated later on. + if (DBT.VerifyAssertions && branchType == BranchType.CALL) throw new RuntimeException("Use the more specific appendCall to create dynamic calls."); + + appendStaticBranch(targetPC, targetLaziness, branchType, -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(targetPC, targetLaziness, BranchType.CALL, retAddr); + } + + private void appendStaticBranch(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. OPT_Instruction jump = Goto.create(GOTO, null); appendInstruction(jump); - UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction(jump, (Laziness)targetLaziness.clone(), targetPC, branchType); + UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction( + jump, (Laziness) targetLaziness.clone(), targetPC, BranchType.CALL); unresolvedDirectBranches.add(unresolvedJump); - //Notify the branch profile about certain types of branches - switch (branchType) { - case CALL: - ps.branchInfo.registerCall(currentPC, targetPC); - return; - - case RETURN: + if (branchType == BranchType.CALL) + ps.branchInfo.registerCall(currentPC, targetPC, retAddr); + else + if (branchType == BranchType.RETURN) ps.branchInfo.registerReturn(currentPC, targetPC); - return; + 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); + } - default: - return; - } + /** + * 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, null, null, fallThrough.makeJumpTarget(), null, 0); + appendInstruction(switchInstr); + + UnresolvedJumpInstruction unresolvedInfo = new UnresolvedJumpInstruction(switchInstr, (Laziness)lazyStateAtJump.clone(), currentPC, branchType); + unresolvedDynamicBranches.add(unresolvedInfo); + + setCurrentBlock(fallThrough); + appendRecordUncaughtBranch(currentPC, targetAddress.copyRO(), branchType, retAddr); + appendTraceExit((Laziness) lazyStateAtJump.clone(), targetAddress.copyRO()); + } - /** Resolve all unresolved direct branch instructions. */ + /** Resolve all unresolved direct branch instructions. */ private void resolveAllDirectBranches() { - + for (int i = 0; i < unresolvedDirectBranches.size(); i++) { - - //Get the jump that we're supposed to resolve - UnresolvedJumpInstruction unresolvedInstr = unresolvedDirectBranches.remove(unresolvedDirectBranches.size() - 1); + + // 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.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); + 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); + report("Properly resolving goto in block " + gotoInstr.getBasicBlock() + + " to " + lazyStateAtJump.makeKey(targetPc) + " " + targetBB); } } } /** - * 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. + * 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. + * 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. + * The address of the target basic block that. * @param lazyStateAtJump - * The lazy state with which we would be entering the block. - * @return - * A basic block that is equivalent to the program counter address <code>targetPc</code> in the - * original binary. + * The lazy state with which we would be entering the block. + * @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, Laziness lazyStateAtJump, BranchType branchtype) { - //Resolve the address of the target block + private OPT_BasicBlock resolveBranchTarget(int targetPc, + Laziness lazyStateAtJump, BranchType branchtype) { + // Resolve the address of the target block OPT_BasicBlock targetBB = findMapping(targetPc, lazyStateAtJump); - - //If the target is already part of this trace, then just use the precompiled target + + // 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 + + /* + * 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 (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(); - - if (DBT_Options.debugBranchResolution) System.out.println("Resolving branch to next block."); + + if (DBT_Options.debugBranchResolution) + System.out.println("Resolving branch to next block."); } targetBB = currentBlock; appendTraceExit(lazyStateAtJump, new OPT_IntConstantOperand(targetPc)); registerMapping(targetPc, lazyStateAtJump, targetBB); - } - else { - //Otherwise we will translate the jump into the trace + } else { + // Otherwise we will translate the jump into the trace translateSubTrace((Laziness) lazyStateAtJump.clone(), targetPc); targetBB = findMapping(targetPc, lazyStateAtJump); } - - if (DBT.VerifyAssertions) DBT._assert(targetBB != null); - + + if (DBT.VerifyAssertions) + DBT._assert(targetBB != null); + return targetBB; } /** - * Resolves all dynamic branches that have been added with + * Resolves all dynamic branches that have been added with * {@link #appendBranch(OPT_RegisterOperand, Laziness, BranchType)}. */ private void resolveDynamicBranches() { for (int i = 0; i < unresolvedDynamicBranches.size(); i++) { - - UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicBranches.get(i); + + UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicBranches + .get(i); Set<Integer> branchDests = getLikelyJumpTargets(unresolvedSwitch.pc); - + resolveSingleDynamicJump(unresolvedSwitch, branchDests); } } - /** - * Resolves a single dynamic jump that has previously been created with + /** + * 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. + * 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. + * 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. + * 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)); - + 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) { if ((destinations.size() > 1) || (lookupswitch.getBasicBlock().nextBasicBlockInCodeOrder() != default_target.target @@ -685,24 +792,28 @@ .size() * 3); int match_no = 0; for (int dest_pc : destinations) { - - 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)); + 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 = resolveBranchTarget(dest_pc, unresolvedJump.lazyStateAtJump, unresolvedJump.type); + 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(), - OPT_BranchProfileOperand.likely()); + new OPT_IntConstantOperand(dest_pc), OPT_ConditionOperand.EQUAL(), + target.makeJumpTarget(), OPT_BranchProfileOperand.likely()); lookupswitch.getBasicBlock().insertOut(target); } } else { @@ -710,44 +821,20 @@ lookupswitch.remove(); } } - - /** - * 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) { - - 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, branchType); - unresolvedDynamicBranches.add(unresolvedInfo); - setCurrentBlock(fallThrough); - appendRecordUncaughtBranch(currentPC, targetAddress.copyRO(), branchType); - appendTraceExit((Laziness) lazyStateAtJump.clone(), targetAddress.copyRO()); - } - /** - * Resolves all dynamic jump targets by making sure the respective basic blocks exist. + * Resolves all dynamic jump targets by making sure the respective basic + * blocks exist. */ private void resolveAllDynamicBranchTargets() { for (int i = 0; i < unresolvedDynamicBranches.size(); i++) { - - UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicBranches.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) { resolveBranchTarget(dest_pc, lazy, unresolvedSwitch.type); @@ -765,31 +852,29 @@ * instruction to translate) */ public void appendTraceExit(Laziness laziness, OPT_Operand nextPc) { - - //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), nextPc)); + appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand( + gc.resultReg, VM_TypeReference.Int), nextPc)); resolveLaziness(laziness); appendInstruction(Goto.create(GOTO, finishBlock.makeJumpTarget())); currentBlock.deleteNormalOut(); currentBlock.insertOut(finishBlock); if (DBT.VerifyAssertions) DBT._assert(currentBlock.getNumberOfNormalOut() == 1); - - //currentBlock = nextBlock; } /** - * 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. + * 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; - } else { + } else { switch (gc.options.getOptLevel()) { case 0: return numberOfInstructions > DBT_Options.instrOpt0; @@ -805,23 +890,23 @@ * Register a branch and link instruction * * @param pc - * the address of the branch instruction + * the address of the branch instruction * @param ret - * the address returned to + * the address returned to * @param dest - * the destination of the branch instruction + * 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>. + * 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. + * 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); @@ -832,7 +917,7 @@ * the trace? * * @param pc - * the address of the branch and link instruction + * the address of the branch and link instruction * @return whether the trace should continue */ public boolean traceContinuesAfterBranchAndLink(int pc) { @@ -886,13 +971,14 @@ * Appends a system call to the current basic block. * * @param lazy - * current translation laziness + * current translation laziness * @param pc - * address of system call instruction + * address of system call instruction */ public void appendSystemCall(Laziness lazy, int pc) { - //We need to make sure that all registers contain their latest values, before - //performing the actual system call. + // We need to make sure that all registers contain their latest values, + // before + // performing the actual system call. resolveLaziness(lazy); spillAllRegisters(); @@ -904,7 +990,7 @@ OPT_Operand psRef = gc.makeLocal(1, psTref); Call.setParam(s, 0, psRef); // Reference to ps, sets 'this' pointer for - // doSysCall + // doSysCall Call.setGuard(s, new OPT_TrueGuardOperand()); Call.setMethod(s, methOp); Call.setAddress(s, @@ -921,13 +1007,14 @@ * Plant a throw of a bad instruction exception * * @param lazy - * current translation laziness + * current translation laziness * @param pc - * the program counter of the bad instruction + * 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. + // We need to make sure that all registers contain their latest values, + // before + // throwing the bad instruction exception. resolveLaziness(lazy); spillAllRegisters(); @@ -946,7 +1033,7 @@ 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( @@ -971,8 +1058,7 @@ appendInstruction(t); - appendTraceExit(lazy, - new OPT_IntConstantOperand(0xEBADC0DE)); + appendTraceExit(lazy, new OPT_IntConstantOperand(0xEBADC0DE)); } /** @@ -980,28 +1066,31 @@ * for call * * @param pc - * the address of the branch instruction + * the address of the branch instruction * @param destination - * the register operand holding the destination - * @param code - * a code that can be a hint of the branch type + * 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) { + 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, 4); + 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 + // instruction Call.setParam(s, 2, destination); // Destination of branch value - Call.setParam(s, 3, new OPT_IntConstantOperand(branchType.ordinal())); // Branch code - // 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( @@ -1135,7 +1224,8 @@ * Get/create a temporary validation variable * * @param num - * a hint to allow for reuse of temps across instructions */ + * a hint to allow for reuse of temps across instructions + */ public OPT_RegisterOperand getTempValidation(int num) { if (DBT.VerifyAssertions) DBT._assert(num == 0); @@ -1149,100 +1239,108 @@ return new OPT_RegisterOperand(result, VM_TypeReference.VALIDATION_TYPE); } } - + /** - * Inserts code into the current block that will use the process space's interpreter - * to execute the given instructions. - * + * Inserts ... [truncated message content] |