public static MethodLocation[] getLocations(BuilderInstruction... instructions) { MethodLocation[] locations = new MethodLocation[instructions.length]; for (int i = 0; i < locations.length; i++) { locations[i] = instructions[i].getLocation(); } return locations; }
public void addNode(ExecutionNode node) { MethodLocation location = node.getOp().getInstruction().getLocation(); locationToNodePile.get(location).add(node); }
public void addInstruction(MethodLocation location, BuilderInstruction instruction) { int index = location.getIndex(); implementation.addInstruction(index, instruction); MethodLocation newLocation = instruction.getLocation(); MethodLocation oldLocation = implementation.getInstructions().get(index + 1).getLocation(); try { java.lang.reflect.Method m = MethodLocation.class.getDeclaredMethod("mergeInto", MethodLocation.class); m.setAccessible(true); m.invoke(oldLocation, newLocation); } catch (Exception e) { log.error("Error invoking MethodLocation.mergeInto(). Wrong dexlib version?", e); } rebuildGraph(); }
protected static TIntObjectMap<MethodLocation> buildAddressToLocation(MutableMethodImplementation implementation) { List<BuilderInstruction> instructions = implementation.getInstructions(); TIntObjectMap<MethodLocation> addressToLocation = new TIntObjectHashMap<>(instructions.size()); for (BuilderInstruction instruction : instructions) { MethodLocation location = instruction.getLocation(); int address = location.getCodeAddress(); addressToLocation.put(address, location); } return addressToLocation; }
private void setupInstruction(BuilderInstruction instruction, Opcode opcode) { when(location.getInstruction()).thenReturn(instruction); when(instruction.getLocation()).thenReturn(location); when(instruction.getCodeUnits()).thenReturn(0); when(instruction.getOpcode()).thenReturn(opcode); }
boolean isNext = child.getAddress() == original.getLocation().getCodeAddress() + original.getCodeUnits(); peepAddresses.add(address); if (isNext) {
private BuilderInstruction buildInstruction22t(Opcode opcode, int offset) { BuilderInstruction instruction = mock(BuilderInstruction.class, withSettings().extraInterfaces(Instruction22t.class)); when(location.getInstruction()).thenReturn(instruction); when(instruction.getLocation()).thenReturn(location); when(instruction.getCodeUnits()).thenReturn(0); when(instruction.getOpcode()).thenReturn(opcode); when(((Instruction22t) instruction).getRegisterA()).thenReturn(ARG1_REGISTER); when(((Instruction22t) instruction).getRegisterB()).thenReturn(ARG2_REGISTER); when(((Instruction22t) instruction).getCodeOffset()).thenReturn(offset); return instruction; }
@Before public void setUp() { vm = mock(VirtualMachine.class); classManager = mock(ClassManager.class); when(vm.getClassManager()).thenReturn(classManager); location = mock(MethodLocation.class); instruction = mock(BuilderInstruction.class, withSettings().extraInterfaces(SwitchPayload.class)); when(location.getInstruction()).thenReturn(instruction); when(location.getCodeAddress()).thenReturn(ADDRESS); when(instruction.getLocation()).thenReturn(location); when(instruction.getCodeUnits()).thenReturn(0); addressToLocation = new TIntObjectHashMap<MethodLocation>(); addressToLocation.put(ADDRESS, location); opFactory = new SwitchPayloadOpFactory(); }
@Before public void setUp() { vm = mock(VirtualMachine.class); mState = mock(MethodState.class); node = mock(ExecutionNode.class); item = mock(HeapItem.class); when(mState.readRegister(REGISTER_B)).thenReturn(item); location = mock(MethodLocation.class); instruction = mock(BuilderInstruction.class, withSettings().extraInterfaces(Instruction12x.class)); when(location.getInstruction()).thenReturn(instruction); when(location.getCodeAddress()).thenReturn(ADDRESS); when(instruction.getLocation()).thenReturn(location); when(instruction.getCodeUnits()).thenReturn(0); when(((Instruction12x) instruction).getRegisterA()).thenReturn(REGISTER_A); when(((Instruction12x) instruction).getRegisterB()).thenReturn(REGISTER_B); addressToLocation = new TIntObjectHashMap<MethodLocation>(); addressToLocation.put(ADDRESS, location); opFactory = new UnaryMathOpFactory(); }
private static int[] buildTerminatingAddresses(List<BuilderInstruction> instructions) { TIntList addresses = new TIntLinkedList(); for (BuilderInstruction instruction : instructions) { int address = instruction.getLocation().getCodeAddress(); Opcode op = instruction.getOpcode(); switch (op) { case RETURN_VOID: case RETURN: case RETURN_WIDE: case RETURN_OBJECT: case THROW: break; default: continue; } addresses.add(address); } return addresses.toArray(); }
@Before public void setUp() { vm = mock(VirtualMachine.class); node = mock(ExecutionNode.class); mState = mock(MethodState.class); location = mock(MethodLocation.class); instruction = mock(BuilderInstruction.class, withSettings().extraInterfaces(Instruction3rc.class, VariableRegisterInstruction.class, ReferenceInstruction.class, RegisterRangeInstruction.class)); when(location.getInstruction()).thenReturn(instruction); when(location.getCodeAddress()).thenReturn(ADDRESS); when(instruction.getLocation()).thenReturn(location); when(instruction.getCodeUnits()).thenReturn(0); Reference ref = new ImmutableTypeReference("[I"); when(((ReferenceInstruction) instruction).getReference()).thenReturn(ref); addressToLocation = new TIntObjectHashMap<MethodLocation>(); addressToLocation.put(ADDRESS, location); opFactory = new FilledNewArrayOpFactory(); }
@Before public void setUp() { vm = mock(VirtualMachine.class); ectx = mock(ExecutionContext.class); mState = mock(MethodState.class); when(ectx.getMethodState()).thenReturn(mState); node = mock(ExecutionNode.class); itemA = mock(HeapItem.class); when(mState.readRegister(REGISTER_A)).thenReturn(itemA); itemB = mock(HeapItem.class); when(mState.readRegister(REGISTER_B)).thenReturn(itemB); setItem = ArgumentCaptor.forClass(HeapItem.class); location = mock(MethodLocation.class); when(location.getCodeAddress()).thenReturn(ADDRESS); instruction = mock(BuilderInstruction.class, withSettings().extraInterfaces(Instruction22c.class)); when(location.getInstruction()).thenReturn(instruction); when(instruction.getLocation()).thenReturn(location); when(instruction.getCodeUnits()).thenReturn(0); when(((Instruction22c) instruction).getRegisterA()).thenReturn(REGISTER_A); when(((Instruction22c) instruction).getRegisterB()).thenReturn(REGISTER_B); FieldReference fieldRef = new ImmutableFieldReference("Lsome/class;", "someMethod", "I"); when(((Instruction22c) instruction).getReference()).thenReturn(fieldRef); addressToLocation = new TIntObjectHashMap<MethodLocation>(); addressToLocation.put(ADDRESS, location); opFactory = new IPutOpFactory(); }
@Before public void setUp() { vm = mock(VirtualMachine.class); mState = mock(MethodState.class); node = mock(ExecutionNode.class); setItem = ArgumentCaptor.forClass(HeapItem.class); itemB = mock(HeapItem.class); when(itemB.isUnknown()).thenReturn(false); when(mState.readRegister(REGISTER_B)).thenReturn(itemB); itemC = mock(HeapItem.class); when(itemC.isUnknown()).thenReturn(false); when(mState.readRegister(REGISTER_C)).thenReturn(itemC); location = mock(MethodLocation.class); instruction = mock(BuilderInstruction.class, withSettings().extraInterfaces(Instruction23x.class)); when(location.getInstruction()).thenReturn(instruction); when(location.getCodeAddress()).thenReturn(ADDRESS); when(instruction.getLocation()).thenReturn(location); when(instruction.getCodeUnits()).thenReturn(0); when(((Instruction23x) instruction).getRegisterA()).thenReturn(REGISTER_A); when(((Instruction23x) instruction).getRegisterB()).thenReturn(REGISTER_B); when(((Instruction23x) instruction).getRegisterC()).thenReturn(REGISTER_C); addressToLocation = new TIntObjectHashMap<MethodLocation>(); addressToLocation.put(ADDRESS, location); opFactory = new CmpOpFactory(); }
@Before public void setUp() { vm = mock(VirtualMachine.class); ectx = mock(ExecutionContext.class); mState = mock(MethodState.class); when(ectx.getMethodState()).thenReturn(mState); node = mock(ExecutionNode.class); itemB = mock(HeapItem.class); when(mState.readRegister(REGISTER_B)).thenReturn(itemB); setItem = ArgumentCaptor.forClass(HeapItem.class); location = mock(MethodLocation.class); instruction = mock(BuilderInstruction.class, withSettings().extraInterfaces(Instruction22c.class)); when(location.getInstruction()).thenReturn(instruction); when(location.getCodeAddress()).thenReturn(ADDRESS); when(instruction.getLocation()).thenReturn(location); when(instruction.getCodeUnits()).thenReturn(0); when(((Instruction22c) instruction).getRegisterA()).thenReturn(REGISTER_A); when(((Instruction22c) instruction).getRegisterB()).thenReturn(REGISTER_B); FieldReference fieldRef = new ImmutableFieldReference("Lsome/class;", "someMethod", "I"); when(((Instruction22c) instruction).getReference()).thenReturn(fieldRef); addressToLocation = new TIntObjectHashMap<MethodLocation>(); addressToLocation.put(ADDRESS, location); opFactory = new IGetOpFactory(); }
when(location.getInstruction()).thenReturn(instruction); when(location.getCodeAddress()).thenReturn(ADDRESS); when(instruction.getLocation()).thenReturn(location); when(instruction.getCodeUnits()).thenReturn(0); when(((Instruction35c) instruction).getRegisterC()).thenReturn(REGISTER_C);
@Test public void replacingInstructionGetsLabelsAtInsertionAddress() { manipulator = OptimizerTester.getGraphManipulator(CLASS_NAME, "hasLabelOnConstantizableOp(I)I"); BuilderInstruction addition = new BuilderInstruction11n(Opcode.CONST_4, 0, 2); assertEquals(1, manipulator.getInstruction(3).getLocation().getLabels().size()); manipulator.replaceInstruction(3, addition); assertEquals(1, manipulator.getInstruction(3).getLocation().getLabels().size()); }
@Override public Op create(MethodLocation location, TIntObjectMap<MethodLocation> addressToLocation, VirtualMachine vm) { BuilderInstruction instruction = (BuilderInstruction) location.getInstruction(); int address = instruction.getLocation().getCodeAddress(); int returnAddress = address + instruction.getCodeUnits(); MethodLocation returnLocation = addressToLocation.get(returnAddress); int branchOffset = ((OffsetInstruction) instruction).getCodeOffset(); int childAddress = address + branchOffset; MethodLocation child = addressToLocation.get(childAddress); Instruction31t instr = (Instruction31t) location.getInstruction(); int register = instr.getRegisterA(); return new FillArrayDataOp(location, child, returnLocation, register); } }
@Test public void replaceInstructionExecutesNewNodeCorrectly() { manipulator = OptimizerTester.getGraphManipulator(CLASS_NAME, "constantPredicate()I"); BuilderInstruction returnVoid = manipulator.getNodePile(4).get(0).getOp().getInstruction(); Label target = returnVoid.getLocation().addNewLabel(); // GOTO_32 shifts addresses around so mappings could break BuilderInstruction replacement = new BuilderInstruction30t(Opcode.GOTO_32, target); manipulator.replaceInstruction(1, replacement); testHeritage(manipulator, 0); }
@Override public Op create(MethodLocation location, TIntObjectMap<MethodLocation> addressToLocation, VirtualMachine vm) { BuilderInstruction instruction = (BuilderInstruction) location.getInstruction(); int address = instruction.getLocation().getCodeAddress(); int branchOffset = ((OffsetInstruction) instruction).getCodeOffset(); int targetAddress = address + branchOffset; MethodLocation child = Utils.getNextLocation(location, addressToLocation); MethodLocation target = addressToLocation.get(targetAddress); String opName = instruction.getOpcode().name; IfType ifType = getIfType(opName); int register1 = ((OneRegisterInstruction) instruction).getRegisterA(); if (instruction instanceof Instruction22t) { // if-* vA, vB, :label Instruction22t instr = (Instruction22t) location.getInstruction(); return new IfOp(location, child, ifType, target, register1, instr.getRegisterB()); } else { // if-*z vA, vB, :label (Instruction 21t) return new IfOp(location, child, ifType, target, register1); } }
private static void test(Object[][] expected, ExecutionGraphManipulator manipulator) { for (Object[] ex : expected) { int address = (Integer) ex[0]; BuilderInstruction actualInstruction = manipulator.getInstruction(address); Opcode expectedOpcode = (Opcode) ex[1]; assertEquals(expectedOpcode, actualInstruction.getOpcode()); Object[][][] exChildren = (Object[][][]) ex[2]; List<ExecutionNode> actualNodePile = manipulator.getNodePile(address); assertEquals(expectedOpcode.name + " @" + address + " node pile size", exChildren.length, actualNodePile.size()); for (int i = 0; i < exChildren.length; i++) { ExecutionNode actualNode = actualNodePile.get(i); List<ExecutionNode> childNodes = actualNode.getChildren(); BuilderInstruction[] children = new BuilderInstruction[childNodes.size()]; for (int j = 0; j < children.length; j++) { children[j] = childNodes.get(j).getOp().getInstruction(); } assertEquals(expectedOpcode.name + " @" + address + " children size", exChildren[i].length, children.length); for (int j = 0; j < exChildren[i].length; j++) { assertEquals(expectedOpcode.name + " @" + address + " child address", (int) exChildren[i][j][0], children[j].getLocation().getCodeAddress()); assertEquals(expectedOpcode.name + " @" + address + " child opcode", exChildren[i][j][1], children[j].getOpcode()); } } } }