|
From: <mic...@us...> - 2007-08-02 12:22:43
|
Revision: 153
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=153&view=rev
Author: michael_baer
Date: 2007-08-02 05:22:44 -0700 (Thu, 02 Aug 2007)
Log Message:
-----------
- Allowing to load/save branch profiles
- Added generic profiling to the Interpreter
- Added support for staged emulation
Modified Paths:
--------------
src/org/binarytranslator/DBT_Options.java
src/org/binarytranslator/Main.java
src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.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/abi/semihosting/AngelSystemCalls.java
src/org/binarytranslator/generic/branchprofile/BranchProfile.java
src/org/binarytranslator/generic/branchprofile/CallAndReturnAddress.java
src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java
src/org/binarytranslator/generic/execution/ExecutionController.java
src/org/binarytranslator/generic/execution/InterpreterController.java
src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java
Added Paths:
-----------
src/org/binarytranslator/generic/execution/ProfilingInterpreterController.java
src/org/binarytranslator/generic/execution/StagedEmulationController.java
Modified: src/org/binarytranslator/DBT_Options.java
===================================================================
--- src/org/binarytranslator/DBT_Options.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/DBT_Options.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -49,7 +49,13 @@
/** Determines how the program will be run (i.e. interpreted, translated etc.) */
public static ExecutionController.Type executionController = ExecutionController.Type.Translator;
+
+ /** A filename to which the runtime profiling information shall be saved. */
+ public static String saveProfileToFile = null;
+ /** A filename from which the runtime profiling information shall be loaded. */
+ public static String loadProfileFromFile = null;
+
/**
* Favour backward branch optimization. Translate backward branch addresses
* before the next instructions (this is the manner of the 601's branch
@@ -183,7 +189,12 @@
gdbStubPort = Integer.parseInt(value);
} else if (arg.equalsIgnoreCase("controller")) {
executionController = ExecutionController.Type.valueOf(value);
- } else {
+ } else if (arg.equalsIgnoreCase("loadProfile")) {
+ loadProfileFromFile = arg;
+ } else if (arg.equalsIgnoreCase("saveProfile")) {
+ saveProfileToFile = arg;
+ }
+ else {
throw new Error("Unknown DBT option: " + arg);
}
}
Modified: src/org/binarytranslator/Main.java
===================================================================
--- src/org/binarytranslator/Main.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/Main.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -9,12 +9,14 @@
package org.binarytranslator;
import java.io.File;
-
import org.binarytranslator.generic.execution.PredecodingThreadedInterpreter;
import org.binarytranslator.generic.execution.DynamicTranslationController;
import org.binarytranslator.generic.execution.ExecutionController;
import org.binarytranslator.generic.execution.GdbController;
import org.binarytranslator.generic.execution.InterpreterController;
+import org.binarytranslator.generic.execution.ProfilingInterpreterController;
+import org.binarytranslator.generic.execution.ProfilingPredecodingInterpreter;
+import org.binarytranslator.generic.execution.StagedEmulationController;
import org.binarytranslator.generic.os.loader.Loader;
import org.binarytranslator.generic.os.process.ProcessSpace;
@@ -93,10 +95,6 @@
System.err.println("Error accesing file: " + args[0] + ". " + e.getMessage());
return;
}
- /*catch (Error e) {
- System.err.println(e.getMessage());
- return;
- }*/
report("Sucessfully created process.");
@@ -108,20 +106,35 @@
//on SUN's VM, only the interpreter has been tested
if (DBT_Options.buildForSunVM) {
DBT_Options.executionController = ExecutionController.Type.PredecodingInterpreter;
-
}
+ //load a previously saved branch profile from file, if the user requested it
+ try {
+ if (DBT_Options.loadProfileFromFile != null)
+ ps.branchInfo.loadFromXML(DBT_Options.loadProfileFromFile);
+ } catch (Exception e) {
+ System.err.println("Error loading branch profile from: " + DBT_Options.loadProfileFromFile);
+ e.printStackTrace();
+ return;
+ }
+
//Create an execution controller and pass execution on to it
ExecutionController controller = null;
switch (DBT_Options.executionController) {
+ case StagedEmulation:
+ controller = new StagedEmulationController(ps);
+ break;
+
case PredecodingInterpreter:
- controller = new PredecodingThreadedInterpreter(ps); //new PredecodingThreadedInterpreter(ps);
- break;
+ controller = DBT_Options.profileDuringInterpretation ?
+ new ProfilingPredecodingInterpreter(ps) : new PredecodingThreadedInterpreter(ps);
+ break;
case Interpreter:
- controller = new InterpreterController(ps);
+ controller = DBT_Options.profileDuringInterpretation ?
+ new ProfilingInterpreterController(ps) : new InterpreterController(ps);
break;
case Translator:
@@ -143,10 +156,11 @@
public static void onExit(int exitcode) {
System.out.println("\nProgram has finished. Exitcode: " + exitcode);
- /*try {
- //ps.branchInfo.saveAsXML("/tmp/profile.xml");
- } catch (IOException e) {
+ try {
+ if (DBT_Options.saveProfileToFile != null)
+ ps.branchInfo.saveAsXML(DBT_Options.saveProfileToFile);
+ } catch (Exception e) {
e.printStackTrace();
- }*/
+ }
}
}
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -20,7 +20,6 @@
import org.binarytranslator.arch.arm.decoder.ARM_Instructions.UndefinedInstruction;
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;
/**
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -385,7 +385,7 @@
this.conditionalInstruction = i;
conditionTrueSuccessor = conditionalInstruction.getSuccessor(pc);
- boolean inThumbMode = (pc & 1) == 0;
+ boolean inThumbMode = (pc & 1) == 1;
if (conditionTrueSuccessor == pc + 4 && !inThumbMode)
successorInstruction = conditionTrueSuccessor; //ARM may have conditional instruction that are not jumps
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -58,11 +58,10 @@
public int translateInstruction(int pc, ARM_Laziness lazy) {
this.pc = pc;
this.lazy = lazy;
- boolean thumb = (pc & 1) != 0;
int instruction;
try {
- if (thumb)
+ if (inThumb())
instruction = ps.memory.loadInstruction16(pc & 0xFFFFFFFE);
else
instruction = ps.memory.loadInstruction32(pc);
@@ -88,7 +87,7 @@
}
ARM_Instruction instr;
- if (thumb)
+ if (inThumb())
instr = ARM_InstructionDecoder.Thumb.decode((short)instruction, translatorFactory);
else
instr = ARM_InstructionDecoder.ARM32.decode(instruction, translatorFactory);
@@ -756,79 +755,99 @@
arm2ir.getCurrentBlock().insertOut(nextInstruction);
arm2ir.getCurrentBlock().insertOut(condBlock);
+ //Query the branch profile to get the probability that this instruction is going to get executed
+ float skipProbability = ps.branchInfo.getBranchProbability(pc, pc + (inThumb() ? 2 : 4));
+ OPT_BranchProfileOperand profileOperand;
+
+ if (skipProbability == -1 || skipProbability == 0.5f) {
+ profileOperand = new OPT_BranchProfileOperand();
+ }
+ else if (skipProbability > 0.8f) {
+ profileOperand = OPT_BranchProfileOperand.always();
+ }
+ else if (skipProbability > 0.5f) {
+ profileOperand = OPT_BranchProfileOperand.likely();
+ }
+ else if (skipProbability < 0.2f) {
+ profileOperand = OPT_BranchProfileOperand.never();
+ }
+ else {
+ profileOperand = OPT_BranchProfileOperand.unlikely();
+ }
+
switch (condition) {
case AL:
throw new RuntimeException("ARM32 instructions with a condition of AL (always) should not be decorated with a ConditionalDecorator.");
case CC:
//return !regs.isCarrySet();
- translateCondition(nextInstruction, arm2ir.getCarryFlag(), OPT_ConditionOperand.NOT_EQUAL());
+ translateCondition(nextInstruction, profileOperand, arm2ir.getCarryFlag(), OPT_ConditionOperand.NOT_EQUAL());
break;
case CS:
//return regs.isCarrySet();
- translateCondition(nextInstruction, arm2ir.getCarryFlag(), OPT_ConditionOperand.EQUAL());
+ translateCondition(nextInstruction, profileOperand, arm2ir.getCarryFlag(), OPT_ConditionOperand.EQUAL());
break;
case EQ:
//return regs.isZeroSet();
- translateCondition(nextInstruction, arm2ir.getZeroFlag(), OPT_ConditionOperand.EQUAL());
+ translateCondition(nextInstruction, profileOperand, arm2ir.getZeroFlag(), OPT_ConditionOperand.EQUAL());
break;
case GE:
//return regs.isNegativeSet() == regs.isOverflowSet();
- translateCondition(nextInstruction, arm2ir.getNegativeFlag(), OPT_ConditionOperand.EQUAL(), arm2ir.getOverflowFlag());
+ translateCondition(nextInstruction, profileOperand, arm2ir.getNegativeFlag(), OPT_ConditionOperand.EQUAL(), arm2ir.getOverflowFlag());
break;
case GT:
- translateCondition_GT(nextInstruction);
+ translateCondition_GT(nextInstruction, profileOperand);
break;
case HI:
- translateCondition_HI(nextInstruction);
+ translateCondition_HI(nextInstruction, profileOperand);
break;
case LE:
- translateCondition_LE(nextInstruction);
+ translateCondition_LE(nextInstruction, profileOperand);
break;
case LS:
- translateCondition_LS(nextInstruction, condBlock);
+ translateCondition_LS(nextInstruction, profileOperand, condBlock);
break;
case LT:
//return regs.isNegativeSet() != regs.isOverflowSet();
- translateCondition(nextInstruction, arm2ir.getNegativeFlag(), OPT_ConditionOperand.NOT_EQUAL(), arm2ir.getOverflowFlag());
+ translateCondition(nextInstruction, profileOperand, arm2ir.getNegativeFlag(), OPT_ConditionOperand.NOT_EQUAL(), arm2ir.getOverflowFlag());
break;
case MI:
//return regs.isNegativeSet();
- translateCondition(nextInstruction, arm2ir.getNegativeFlag(), OPT_ConditionOperand.EQUAL());
+ translateCondition(nextInstruction, profileOperand, arm2ir.getNegativeFlag(), OPT_ConditionOperand.EQUAL());
break;
case NE:
//return !regs.isZeroSet();
- translateCondition(nextInstruction, arm2ir.getZeroFlag(), OPT_ConditionOperand.NOT_EQUAL());
+ translateCondition(nextInstruction, profileOperand, arm2ir.getZeroFlag(), OPT_ConditionOperand.NOT_EQUAL());
break;
case NV:
//never execute this instruction
- translateCondition(nextInstruction, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL());
+ translateCondition(nextInstruction, profileOperand, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL());
break;
case PL:
//return !regs.isNegativeSet();
- translateCondition(nextInstruction, arm2ir.getNegativeFlag(), OPT_ConditionOperand.NOT_EQUAL());
+ translateCondition(nextInstruction, profileOperand, arm2ir.getNegativeFlag(), OPT_ConditionOperand.NOT_EQUAL());
break;
case VC:
//return !regs.isOverflowSet();
- translateCondition(nextInstruction, arm2ir.getOverflowFlag(), OPT_ConditionOperand.NOT_EQUAL());
+ translateCondition(nextInstruction, profileOperand, arm2ir.getOverflowFlag(), OPT_ConditionOperand.NOT_EQUAL());
break;
case VS:
//return regs.isOverflowSet();
- translateCondition(nextInstruction, arm2ir.getOverflowFlag(), OPT_ConditionOperand.EQUAL());
+ translateCondition(nextInstruction, profileOperand, arm2ir.getOverflowFlag(), OPT_ConditionOperand.EQUAL());
break;
default:
@@ -839,17 +858,17 @@
conditionalInstruction.translate();
}
- private void translateCondition(OPT_BasicBlock nextInstruction, OPT_Operand operand, OPT_ConditionOperand condition) {
- translateCondition(nextInstruction, operand, condition, new OPT_IntConstantOperand(1));
+ private void translateCondition(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability, OPT_Operand operand, OPT_ConditionOperand condition) {
+ translateCondition(nextInstruction, skipProbability, operand, condition, new OPT_IntConstantOperand(1));
}
- private void translateCondition(OPT_BasicBlock nextInstruction, OPT_Operand lhs, OPT_ConditionOperand condition, OPT_Operand rhs) {
+ private void translateCondition(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability, OPT_Operand lhs, OPT_ConditionOperand condition, OPT_Operand rhs) {
condition = condition.flipCode();
- arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), lhs, rhs, condition, nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand()));
+ arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), lhs, rhs, condition, nextInstruction.makeJumpTarget(), skipProbability));
}
- private void translateCondition_HI(OPT_BasicBlock nextInstruction) {
+ private void translateCondition_HI(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability) {
//return regs.isCarrySet() && !regs.isZeroSet();
OPT_Operand carry = arm2ir.getCarryFlag();
OPT_Operand zero = arm2ir.getZeroFlag();
@@ -858,10 +877,10 @@
arm2ir.appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_OR, result, carry,
new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
- arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand()));
+ arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), skipProbability));
}
- private void translateCondition_LS(OPT_BasicBlock nextInstruction, OPT_BasicBlock actualInstruction) {
+ private void translateCondition_LS(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability, OPT_BasicBlock actualInstruction) {
//return !regs.isCarrySet() || regs.isZeroSet();
OPT_Operand carry = arm2ir.getCarryFlag();
OPT_Operand zero = arm2ir.getZeroFlag();
@@ -869,7 +888,7 @@
OPT_RegisterOperand result = arm2ir.getTempInt(0);
arm2ir.appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, result, carry, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
- arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand()));
+ arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), skipProbability));
/* cond1.deleteNormalOut();
cond1.insertOut(cond2);
@@ -885,7 +904,7 @@
cond2.insertOut(actualInstruction);*/
}
- private void translateCondition_GT(OPT_BasicBlock nextInstruction) {
+ private void translateCondition_GT(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability) {
//return (regs.isNegativeSet() == regs.isOverflowSet()) && !regs.isZeroSet();
OPT_Operand negative = arm2ir.getNegativeFlag();
OPT_Operand overflow = arm2ir.getOverflowFlag();
@@ -895,10 +914,10 @@
arm2ir.appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_OR, result, negative,
overflow, OPT_ConditionOperand.NOT_EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
- arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand()));
+ arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), skipProbability));
}
- private void translateCondition_LE(OPT_BasicBlock nextInstruction) {
+ private void translateCondition_LE(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability) {
//return regs.isZeroSet() || (regs.isNegativeSet() != regs.isOverflowSet());
OPT_Operand negative = arm2ir.getNegativeFlag();
OPT_Operand overflow = arm2ir.getOverflowFlag();
@@ -908,7 +927,7 @@
arm2ir.appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, result, negative,
overflow, OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
- arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand()));
+ arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), skipProbability));
}
@Override
Modified: src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java
===================================================================
--- src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -13,6 +13,7 @@
import org.binarytranslator.DBT;
import org.binarytranslator.DBT_Options;
+import org.binarytranslator.Main;
import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace;
/**
@@ -691,6 +692,7 @@
@Override
public void execute() {
ps.finished = true;
+ Main.onExit(0);
}
}
Modified: src/org/binarytranslator/generic/branchprofile/BranchProfile.java
===================================================================
--- src/org/binarytranslator/generic/branchprofile/BranchProfile.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/generic/branchprofile/BranchProfile.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -121,7 +121,7 @@
throw new IOException("File is not a valid XML branch profile.");
int targetAddress = Integer.parseInt(((Element)target).getAttribute("address"));
- int branchCount = Integer.parseInt(((Element)target).getAttribute("address"));
+ int branchCount = Integer.parseInt(((Element)target).getAttribute("branchCount"));
targetsAndFrequencies.put(targetAddress, branchCount);
}
@@ -131,8 +131,6 @@
public void toXML(Document doc, Element parentNode) {
Element branchInfo = parentNode;
- Element targets = doc.createElement("targets");
-
for (Entry<Integer, Integer> branchTarget : destinationsAndFrequencies.entrySet()) {
int targetAddress = branchTarget.getKey();
int branchCount = branchTarget.getValue();
@@ -142,8 +140,6 @@
branchTargetElement.setAttribute("address", Integer.toString(targetAddress));
branchTargetElement.setAttribute("branchCount", Integer.toString(branchCount));
}
-
- branchInfo.appendChild(targets);
}
}
@@ -243,6 +239,33 @@
branchSites.put(origin, branch);
}
}
+
+ /**
+ * Returns the probability of a branch from <code>origin</code> to <code>target</code>.
+ *
+ * @param origin
+ * The address at which the branch is taking place.
+ * @param target
+ * The address to which the branch is taking place.
+ * @return
+ * The probability of the branch as a value between 0 and 1. The function returns -1, if the probability
+ * cannot be estimated.
+ */
+ public float getBranchProbability(int origin, int target) {
+ BranchInformation branch = branchSites.get(origin);
+
+ if (branch == null || branch.executionCount == 0) {
+ return -1f;
+ }
+
+ Integer branchesToTarget = branch.getTargetsAndFrequencies().get(target);
+
+ if (branchesToTarget == null) {
+ return 0f;
+ }
+
+ return branchesToTarget / (float)branch.executionCount;
+ }
/**
* Given an address within a procedure, returns the (most likely) procedure
@@ -271,7 +294,15 @@
* The address to which it took place.
*/
public void profileBranch(int origin, int target) {
- throw new RuntimeException("Not yet implemented.");
+
+ BranchInformation branch = branchSites.get(origin);
+
+ if (branch == null) {
+ branch = new BranchInformation();
+ branchSites.put(origin, branch);
+ }
+
+ branch.profile(target);
}
/**
@@ -288,8 +319,21 @@
return (branch == null) ? null : branch.getTargets();
}
+ /**
+ * Loads a branch profile from a file.
+ *
+ * @param filename
+ * The name of the file that the branch profile is loaded from.
+ * @throws IOException
+ * An exception that is thrown if an error occurs reading that file.
+ */
public void loadFromXML(String filename) throws IOException {
+ //clear previous profile data
+ procedures.clear();
+ branchSites.clear();
+
+ //create a XML document builder and an XML document
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
Document doc;
try {
@@ -303,34 +347,54 @@
if (DBT.VerifyAssertions) DBT._assert(doc != null);
+ //Check the root-name of the document
Element root = doc.getDocumentElement();
-
if (!root.getNodeName().equals("branch-profile"))
throw new IOException("File is not a valid XML branch profile.");
- Node branches = null;
-
+ //interate over the main document, parsing the different sections
for (int i = 0; i < root.getChildNodes().getLength(); i++) {
- Node node = root.getChildNodes().item(0);
+ Node node = root.getChildNodes().item(i);
+ String nodeName = node.getNodeName();
- if (node.getNodeName().equals("branches")) {
- branches = node;
- break;
+ if (node.getNodeType() != Node.ELEMENT_NODE) {
+ continue;
}
- }
-
- 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.");
+ if (nodeName.equals("branches")) {
- int address = Integer.parseInt(((Element)siteNode).getAttribute("address"));
- BranchInformation branchInfo = BranchInformation.fromXML((Element)siteNode);
- branchSites.put(address, branchInfo);
+ //this is the section which contains the branch information.
+ for (int n = 0; n < node.getChildNodes().getLength(); n++) {
+ Node branchNode = node.getChildNodes().item(n);
+
+ if (branchNode.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+
+ if (!branchNode.getNodeName().equals("branch"))
+ throw new IOException("File is not a valid XML branch profile.");
+
+ int address = Integer.parseInt(((Element)branchNode).getAttribute("address"));
+ BranchInformation branchInfo = BranchInformation.fromXML((Element)branchNode);
+ branchSites.put(address, branchInfo);
+ }
+ }
+ else
+ if (nodeName.equals("procedures")) {
+
+ //this is the section with procedure information
+ for (int n = 0; n < node.getChildNodes().getLength(); n++) {
+ Node procedureInfo = node.getChildNodes().item(n);
+
+ if (procedureInfo.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+
+ ProcedureInformation pi = ProcedureInformation.fromXML((Element)procedureInfo);
+ procedures.put(pi.getEntryAddress(), pi);
+ }
+ }
+ else {
+ throw new IOException("This is not a valid XML branch profile.");
+ }
}
}
@@ -387,6 +451,15 @@
branchInfo.toXML(doc, branchSiteElement);
}
+ Element proceduresElement = doc.createElement("procedures");
+ root.appendChild(proceduresElement);
+
+ for (ProcedureInformation procedure : procedures.values()) {
+ Element procedureElement = doc.createElement("procedure");
+ proceduresElement.appendChild(procedureElement);
+ procedure.toXML(doc, procedureElement);
+ }
+
//Output the resulting XML document
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer;
@@ -395,6 +468,7 @@
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(outputStream);
transformer.transform(source, result);
+ outputStream.close();
} catch (Exception e) {
e.printStackTrace();
Modified: src/org/binarytranslator/generic/branchprofile/CallAndReturnAddress.java
===================================================================
--- src/org/binarytranslator/generic/branchprofile/CallAndReturnAddress.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/generic/branchprofile/CallAndReturnAddress.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -12,14 +12,11 @@
* Object for recording a call site and its corresponding return address
*/
class CallAndReturnAddress {
- /**
- * Call site address
- */
+
+ /** The address at which the call is taking place.*/
private int callSite;
- /**
- * Return address
- */
+ /** The address to which the call shall return. */
private int returnAddress;
/**
@@ -35,24 +32,29 @@
this.returnAddress = returnAddress;
}
- /**
- * Get call site address
- */
+ /** Get call site address */
int getCallSite() {
return callSite;
}
- /**
- * Get return address
- */
+ /** Get return address */
int getReturnAddress() {
return returnAddress;
}
+
+ @Override
+ public int hashCode() {
+ return callSite;
+ }
- /**
- * Are two call sites the same?
- */
+ @Override
public boolean equals(Object obj) {
- return ((CallAndReturnAddress) obj).callSite == callSite;
+
+ if (!(obj instanceof CallAndReturnAddress)) {
+ return false;
+ }
+
+ CallAndReturnAddress other = ((CallAndReturnAddress) obj);
+ return other.callSite == callSite && other.returnAddress == returnAddress;
}
}
Modified: src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java
===================================================================
--- src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -19,20 +19,15 @@
* Objects capturing information about what looks like a method
*/
class ProcedureInformation {
- /**
- * Entry point to the procedure
- */
+
+ /** Entry point to the procedure */
private final int entry;
- /**
- * Set of locations that call the procedure and the corressponding return
- * address
- */
+ /** Set of locations that call the procedure and the corressponding return
+ * address. */
private HashSet<CallAndReturnAddress> callSitesAndReturnAddresses;
- /**
- * Set of locations within the procedure that return
- */
+ /** Set of locations within the procedure that return */
private HashSet<Integer> returnSites;
/**
@@ -50,8 +45,15 @@
}
}
- private ProcedureInformation(int entry) {
+ /**
+ * Constructor
+ *
+ * @param entry
+ * starting address of the procedure
+ */
+ public ProcedureInformation(int entry) {
this.entry = entry;
+ callSitesAndReturnAddresses = new HashSet<CallAndReturnAddress>();
}
/**
@@ -64,23 +66,32 @@
* @param returnAddress
* the corresponding return address
*/
- ProcedureInformation(int entry, int callSite, int returnAddress) {
- this.entry = entry;
- callSitesAndReturnAddresses = new HashSet<CallAndReturnAddress>();
+ public ProcedureInformation(int entry, int callSite, int returnAddress) {
+ this(entry);
+
callSitesAndReturnAddresses.add(new CallAndReturnAddress(callSite,
returnAddress));
}
+
+ /**
+ * Returns the address at which this procedure starts.
+ * @return
+ * The address at which the procedure starts.
+ */
+ public int getEntryAddress() {
+ return entry;
+ }
/**
* Register a call (branch and link) instruction
*
- * @param pc
- * the address of the branch instruction
+ * @param atAddress
+ * the address of the call instruction
* @param ret
* the address that will be returned to
*/
- public void registerCall(int pc, int ret) {
- CallAndReturnAddress call_tuple = new CallAndReturnAddress(pc, ret);
+ public void registerCall(int atAddress, int ret) {
+ CallAndReturnAddress call_tuple = new CallAndReturnAddress(atAddress, ret);
if (!callSitesAndReturnAddresses.contains(call_tuple)) {
callSitesAndReturnAddresses.add(call_tuple);
}
@@ -89,15 +100,15 @@
/**
* Register a return (branch to link register) instruction
*
- * @param pc
+ * @param atAddress
* the address of the branch instruction
*/
- public void registerReturn(int pc) {
+ public void registerReturn(int atAddress) {
if (returnSites == null) {
returnSites = new HashSet<Integer>();
}
- returnSites.add(new Integer(pc));
+ returnSites.add(new Integer(atAddress));
}
/**
@@ -121,13 +132,17 @@
}
procedure.appendChild(callSites);
- Element returnSites = doc.createElement("returnsites");
- for (Integer returnSite : this.returnSites) {
- Element returnSiteNode = doc.createElement("return");
- returnSiteNode.setAttribute("at", returnSite.toString());
- returnSites.appendChild(returnSiteNode);
+ if (returnSites != null) {
+ Element returnSitesElement = doc.createElement("returnsites");
+ procedure.appendChild(returnSitesElement);
+
+ for (Integer returnSite : returnSites) {
+ Element returnSiteNode = doc.createElement("return");
+ returnSiteNode.setAttribute("at", returnSite.toString());
+ returnSitesElement.appendChild(returnSiteNode);
+ }
+
}
- procedure.appendChild(returnSites);
}
/**
@@ -156,7 +171,7 @@
if (callsite.getNodeType() != Node.ELEMENT_NODE)
continue;
- if (callsite.getNodeName().equals("call"))
+ if (!callsite.getNodeName().equals("call"))
throw new Error("The given XML node is not a valid ProcedureInformation entity.");
int callFrom = Integer.parseInt(((Element)callsite).getAttribute("from"));
@@ -166,6 +181,9 @@
}
}
else if (childNode.getNodeName().equals("returnsites")) {
+
+ pi.returnSites = new HashSet<Integer>();
+
//parse return sites
for (int n = 0; n < childNode.getChildNodes().getLength(); n++) {
Node callsite = childNode.getChildNodes().item(n);
@@ -174,7 +192,7 @@
if (callsite.getNodeType() != Node.ELEMENT_NODE)
continue;
- if (callsite.getNodeName().equals("return"))
+ if (!callsite.getNodeName().equals("return"))
throw new Error("The given XML node is not a valid ProcedureInformation entity.");
int returnAt = Integer.parseInt(((Element)callsite).getAttribute("at"));
Modified: src/org/binarytranslator/generic/execution/ExecutionController.java
===================================================================
--- src/org/binarytranslator/generic/execution/ExecutionController.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/generic/execution/ExecutionController.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -9,6 +9,7 @@
Translator,
Interpreter,
PredecodingInterpreter,
+ StagedEmulation,
GDB
}
Modified: src/org/binarytranslator/generic/execution/InterpreterController.java
===================================================================
--- src/org/binarytranslator/generic/execution/InterpreterController.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/generic/execution/InterpreterController.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -13,23 +13,16 @@
@Override
public void run() {
Interpreter interpreter = ps.createInterpreter();
-
int pc = ps.getCurrentInstructionAddress();
while (!ps.finished) {
- Interpreter.Instruction instruction = interpreter.decode(pc);
- //System.out.println(String.format("[0x%x] %s", pc, instruction.toString()));
-
+ Interpreter.Instruction instruction = interpreter.decode(pc);
instruction.execute();
- //System.out.println(ps.toString());
int nextInstruction = instruction.getSuccessor(pc);
if (nextInstruction == -1) {
nextInstruction = ps.getCurrentInstructionAddress();
-
- if (DBT_Options.profileDuringInterpretation)
- ps.branchInfo.profileBranch(pc, ps.getCurrentInstructionAddress());
}
else {
ps.setCurrentInstructionAddress(nextInstruction);
Modified: src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java
===================================================================
--- src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -8,10 +8,33 @@
import org.binarytranslator.generic.decoder.Interpreter;
import org.binarytranslator.generic.os.process.ProcessSpace;
+/**
+ * Execution controller that implements predecoding, threaded interpretation.
+ *
+ */
public class PredecodingThreadedInterpreter extends ExecutionController {
+ /** The controller keeps a cache of commonly used code traces. Each trace is essentially a dynamic basic block.
+ * This HashMap maps the address of a trace's first instruction to its dynamic basic block. */
private final HashMap<Integer, List<Interpreter.Instruction>> traceCache = new HashMap<Integer, List<Interpreter.Instruction>>();
+
+ /** The interpreter that is used to perform the actual execution of single instructions. */
private final Interpreter interpreter;
+ /** Default constructor. */
+ public PredecodingThreadedInterpreter(ProcessSpace ps) {
+ super(ps);
+ interpreter = ps.createInterpreter();
+ }
+
+ /**
+ * Returns the dynamic basic block of instructions, starting it at address <code>pc</code>.
+ * This function also manages the trace cache ({@link #traceCache}).
+ *
+ * @param pc
+ * The address at which the dynamic basic block starts.
+ * @return
+ * A list of instructions that form the dynamic basic block.
+ */
private List<Interpreter.Instruction> getTrace(int pc) {
List<Interpreter.Instruction> cachedTrace = traceCache.get(pc);
@@ -42,6 +65,14 @@
return newTrace;
}
+ /**
+ * Executes a list of instructions. It is assumed that the first instruction starts at address <code>pc</code>.
+ *
+ * @param trace
+ * The list of instructions that is to be executed.
+ * @param pc
+ * The address of the first instruction.
+ */
protected void executeTrace(List<Interpreter.Instruction> trace, int pc) {
Iterator<Interpreter.Instruction> instructions = trace.iterator();
@@ -57,11 +88,6 @@
break;
}
}
-
- public PredecodingThreadedInterpreter(ProcessSpace ps) {
- super(ps);
- interpreter = ps.createInterpreter();
- }
@Override
public final void run() {
Added: src/org/binarytranslator/generic/execution/ProfilingInterpreterController.java
===================================================================
--- src/org/binarytranslator/generic/execution/ProfilingInterpreterController.java (rev 0)
+++ src/org/binarytranslator/generic/execution/ProfilingInterpreterController.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -0,0 +1,36 @@
+package org.binarytranslator.generic.execution;
+
+import org.binarytranslator.generic.decoder.Interpreter;
+import org.binarytranslator.generic.os.process.ProcessSpace;
+
+public class ProfilingInterpreterController extends ExecutionController {
+
+ public ProfilingInterpreterController(ProcessSpace ps) {
+ super(ps);
+ }
+
+ @Override
+ public void run() {
+ Interpreter interpreter = ps.createInterpreter();
+
+ int pc = ps.getCurrentInstructionAddress();
+
+ while (!ps.finished) {
+ Interpreter.Instruction instruction = interpreter.decode(pc);
+
+ instruction.execute();
+ int nextInstruction = instruction.getSuccessor(pc);
+
+ if (nextInstruction == -1) {
+ nextInstruction = ps.getCurrentInstructionAddress();
+ ps.branchInfo.profileBranch(pc, ps.getCurrentInstructionAddress());
+ }
+ else {
+ ps.setCurrentInstructionAddress(nextInstruction);
+ }
+
+ pc = nextInstruction;
+ }
+ }
+
+}
Added: src/org/binarytranslator/generic/execution/StagedEmulationController.java
===================================================================
--- src/org/binarytranslator/generic/execution/StagedEmulationController.java (rev 0)
+++ src/org/binarytranslator/generic/execution/StagedEmulationController.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -0,0 +1,121 @@
+package org.binarytranslator.generic.execution;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import org.binarytranslator.DBT;
+import org.binarytranslator.DBT_Options;
+import org.binarytranslator.generic.decoder.Interpreter;
+import org.binarytranslator.generic.os.process.ProcessSpace;
+import org.binarytranslator.vmInterface.DBT_Trace;
+import org.binarytranslator.vmInterface.DynamicCodeRunner;
+import org.jikesrvm.ArchitectureSpecific.VM_CodeArray;
+
+public class StagedEmulationController extends ExecutionController {
+
+ private final class Trace {
+ public final List<Interpreter.Instruction> instructions;
+ public int value;
+ public DBT_Trace compiledTrace;
+
+ public Trace(List<Interpreter.Instruction> instructions) {
+ this.instructions = instructions;
+ value = 0;
+ }
+ }
+
+ private final HashMap<Integer, Trace> traceCache = new HashMap<Integer, Trace>();
+ private final Interpreter interpreter;
+
+ private Trace getTrace(int pc) {
+ Trace cachedTrace = traceCache.get(pc);
+
+ if (cachedTrace != null)
+ return cachedTrace;
+
+ int traceStart = pc;
+ ArrayList<Interpreter.Instruction> instructions = new ArrayList<Interpreter.Instruction>(5);
+
+ while (true) {
+ Interpreter.Instruction instruction = interpreter.decode(pc);
+ pc = instruction.getSuccessor(pc);
+ instructions.add(instruction);
+
+ //is the successor to this instruction known?
+ if (pc == -1) {
+ //No, so stop and create a trace from the decoded instructions
+ Trace newTrace = new Trace(instructions);
+
+ if (instructions.size() > 3) {
+ //add this trace to the trace cache, if it contains enough instructions
+ traceCache.put(traceStart, newTrace);
+ }
+
+ return newTrace;
+ }
+ }
+ }
+
+ private void compileTrace(Trace trace, int pc) {
+ if (DBT.VerifyAssertions) DBT._assert(trace.compiledTrace == null);
+
+ trace.compiledTrace = new DBT_Trace(ps, pc);
+ trace.compiledTrace.compile();
+ }
+
+ private void executeTrace(Trace trace, int pc) {
+
+ //check if the trace is being executed very frequently...
+ if (trace.value > 20) {
+
+ if (DBT_Options.debugTranslation)
+ System.out.println("Switching to interpretation at address 0x" + Integer.toHexString(pc));
+
+ //yes, so we should rather try to execute a translated version
+ if (trace.compiledTrace == null) {
+ //compile the trace, if necessary
+ compileTrace(trace, pc);
+ if (DBT.VerifyAssertions) DBT._assert(trace.compiledTrace != null);
+ }
+
+ //execute the trace
+ VM_CodeArray code = trace.compiledTrace.getCurrentCompiledMethod().getEntryCodeArray();
+ ps.setCurrentInstructionAddress(DynamicCodeRunner.invokeCode(code, ps));
+ }
+ else {
+ trace.value += trace.instructions.size();
+ }
+
+ Iterator<Interpreter.Instruction> instructions = trace.instructions.iterator();
+ while (true) {
+ Interpreter.Instruction instr = instructions.next();
+ instr.execute();
+
+ if (instructions.hasNext()) {
+ pc = instr.getSuccessor(pc);
+ ps.setCurrentInstructionAddress(pc);
+ }
+ else
+ break;
+ }
+ }
+
+ public StagedEmulationController(ProcessSpace ps) {
+ super(ps);
+ interpreter = ps.createInterpreter();
+ }
+
+ @Override
+ public void run() {
+ int pc = ps.getCurrentInstructionAddress();
+
+ while (!ps.finished) {
+
+ Trace trace = getTrace(pc);
+ executeTrace(trace, pc);
+ pc = ps.getCurrentInstructionAddress();
+ }
+ }
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|