@Nullable private BuilderInstruction getFirstNonNop(int startIndex) { for (int i = startIndex; i < instructionList.size() - 1; i++) { BuilderInstruction instruction = instructionList.get(i).instruction; assert instruction != null; if (instruction.getOpcode() != Opcode.NOP) { return instruction; } } return null; }
@Nullable private MethodLocation findSwitchForPayload(@Nonnull MethodLocation payloadLocation) { MethodLocation location = payloadLocation; MethodLocation switchLocation = null; do { for (Label label : location.getLabels()) { if (label instanceof SwitchPayloadReferenceLabel) { if (switchLocation != null) { throw new IllegalStateException("Multiple switch instructions refer to the same payload. " + "This is not currently supported. Please file a bug :)"); } switchLocation = ((SwitchPayloadReferenceLabel) label).switchLocation; } } // A switch instruction can refer to the payload instruction itself, or to a nop before the payload // instruction. // We need to search for all occurrences of a switch reference, so we can detect when multiple switch // statements refer to the same payload // TODO: confirm that it could refer to the first NOP in a series of NOPs preceding the payload if (location.index == 0) { return switchLocation; } location = instructionList.get(location.index - 1); if (location.instruction == null || location.instruction.getOpcode() != Opcode.NOP) { return switchLocation; } } while (true); }
public final String getName() { if (getInstruction() != null) { return getInstruction().getOpcode().name; } else { // Happens during instruction removal return "*null instr*"; } }
private void removeMoveResultIfNecessary(int address) { BuilderInstruction instruction = manipulator.getInstruction(address); int nextAddress = address + instruction.getCodeUnits(); BuilderInstruction nextInstr = manipulator.getInstruction(nextAddress); String opName = nextInstr.getOpcode().name; if (opName.startsWith("move-result")) { manipulator.removeInstruction(nextAddress); } }
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); }
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; }
@Test public void canFloatToDouble() { Float value = 11204.0345F; when(item.getValue()).thenReturn(value); when(item.getType()).thenReturn("F"); when(instruction.getOpcode()).thenReturn(Opcode.FLOAT_TO_DOUBLE); op = (UnaryMathOp) opFactory.create(location, addressToLocation, vm); op.execute(node, mState); verify(mState, times(1)).assignRegister(eq(REGISTER_A), eq(new HeapItem(value.doubleValue(), "D"))); }
@Test public void canFloatToInt() { Float value = 11204.0345F; when(item.getValue()).thenReturn(value); when(item.getType()).thenReturn("F"); when(instruction.getOpcode()).thenReturn(Opcode.FLOAT_TO_INT); op = (UnaryMathOp) opFactory.create(location, addressToLocation, vm); op.execute(node, mState); verify(mState, times(1)).assignRegister(eq(REGISTER_A), eq(new HeapItem(value.intValue(), "I"))); }
@Test public void canLongToDouble() { Long value = 112040345L; when(item.getValue()).thenReturn(value); when(item.getType()).thenReturn("J"); when(instruction.getOpcode()).thenReturn(Opcode.LONG_TO_DOUBLE); op = (UnaryMathOp) opFactory.create(location, addressToLocation, vm); op.execute(node, mState); verify(mState, times(1)).assignRegister(eq(REGISTER_A), eq(new HeapItem(value.doubleValue(), "D"))); }
@Test public void canLongToInt() { Long value = 112040345L; when(item.getValue()).thenReturn(value); when(item.getType()).thenReturn("J"); when(instruction.getOpcode()).thenReturn(Opcode.LONG_TO_INT); op = (UnaryMathOp) opFactory.create(location, addressToLocation, vm); op.execute(node, mState); verify(mState, times(1)).assignRegister(eq(REGISTER_A), eq(new HeapItem(value.intValue(), "I"))); }
@Test public void canDoubleToInt() { Double value = 11204.0345612345D; when(item.getValue()).thenReturn(value); when(item.getType()).thenReturn("D"); when(instruction.getOpcode()).thenReturn(Opcode.DOUBLE_TO_INT); op = (UnaryMathOp) opFactory.create(location, addressToLocation, vm); op.execute(node, mState); verify(mState, times(1)).assignRegister(eq(REGISTER_A), eq(new HeapItem(value.intValue(), "I"))); }
@Test public void canDoubleToLong() { Double value = 11204.0345612345D; when(item.getValue()).thenReturn(value); when(item.getType()).thenReturn("D"); when(instruction.getOpcode()).thenReturn(Opcode.DOUBLE_TO_LONG); op = (UnaryMathOp) opFactory.create(location, addressToLocation, vm); op.execute(node, mState); verify(mState, times(1)).assignRegister(eq(REGISTER_A), eq(new HeapItem(value.longValue(), "J"))); }
@Test public void canIntToByte() { Integer value = 10; when(item.getValue()).thenReturn(value); when(item.getType()).thenReturn("I"); when(instruction.getOpcode()).thenReturn(Opcode.INT_TO_BYTE); op = (UnaryMathOp) opFactory.create(location, addressToLocation, vm); op.execute(node, mState); verify(mState, times(1)).assignRegister(eq(REGISTER_A), eq(new HeapItem(value.byteValue(), "B"))); }
@Test public void testIGetReturnsUnknownValueOfCorrectType() { when(instruction.getOpcode()).thenReturn(Opcode.IPUT); op = (IPutOp) opFactory.create(location, addressToLocation, vm); op.execute(node, ectx); verify(mState, times(1)).readRegister(eq(REGISTER_A)); verify(mState, times(1)).readRegister(eq(REGISTER_B)); verify(mState, times(1)).assignRegister(eq(REGISTER_B), any(HeapItem.class)); assertEquals("iput r" + REGISTER_A + ", r" + REGISTER_B + ", Lsome/class;->someMethod:I", op.toString()); }
@Test public void canFloatToLong() { Float value = 11204.0345F; when(item.getValue()).thenReturn(value); when(item.getType()).thenReturn("F"); when(instruction.getOpcode()).thenReturn(Opcode.FLOAT_TO_LONG); op = (UnaryMathOp) opFactory.create(location, addressToLocation, vm); op.execute(node, mState); verify(mState, times(1)).assignRegister(eq(REGISTER_A), eq(new HeapItem(value.longValue(), "J"))); }
@Test public void canLongToFloat() { Long value = 112040345L; when(item.getValue()).thenReturn(value); when(item.getType()).thenReturn("J"); when(instruction.getOpcode()).thenReturn(Opcode.LONG_TO_FLOAT); op = (UnaryMathOp) opFactory.create(location, addressToLocation, vm); op.execute(node, mState); verify(mState, times(1)).assignRegister(eq(REGISTER_A), eq(new HeapItem(value.floatValue(), "F"))); }
@Test public void canDoubleToFloat() { Double value = 11204.0345612345D; when(item.getValue()).thenReturn(value); when(item.getType()).thenReturn("D"); when(instruction.getOpcode()).thenReturn(Opcode.DOUBLE_TO_FLOAT); op = (UnaryMathOp) opFactory.create(location, addressToLocation, vm); op.execute(node, mState); verify(mState, times(1)).assignRegister(eq(REGISTER_A), eq(new HeapItem(value.floatValue(), "F"))); assertEquals("double-to-float r" + REGISTER_A + ", r" + REGISTER_B, op.toString()); }
@Test public void testIGetReturnsUnknownValueOfCorrectType() { when(instruction.getOpcode()).thenReturn(Opcode.IGET); op = (IGetOp) opFactory.create(location, addressToLocation, vm); op.execute(node, ectx); verify(mState, times(1)).readRegister(eq(REGISTER_B)); verify(mState, times(1)).assignRegister(eq(REGISTER_A), setItem.capture()); assertEquals(UnknownValue.class, setItem.getValue().getValue().getClass()); assertEquals("I", setItem.getValue().getType()); assertEquals("iget r" + REGISTER_A + ", r" + REGISTER_B + ", Lsome/class;->someMethod:I", op.toString()); }
@Test public void constantPredicateReplacedWithUnconditionalBranch() { // I say phrases like "unconditional branch" instead of "goto". // I'm also a riot at dinner parties. ExecutionGraphManipulator manipulator = getOptimizedGraph(METHOD_NAME); BuilderInstruction instruction = manipulator.getInstruction(1); assertEquals(Opcode.GOTO_32, instruction.getOpcode()); assertEquals(4, ((OffsetInstruction) instruction).getCodeOffset()); }
@Test public void doesNotDetectInstanceInitializer() { VirtualMachine vm = VMTester.spawnVM(true); VirtualClass virtualClass = vm.getClassManager().getVirtualClass(CLASS_NAME); VMState initial = new VMState(); initial.setRegisters(0, new UninitializedInstance(virtualClass), CLASS_NAME); String methodName = "<init>()V"; ExecutionGraphManipulator manipulator = OptimizerTester.getGraphManipulator(CLASS_NAME, methodName, initial); DeadRemovalStrategy strategy = new DeadRemovalStrategy(manipulator); strategy.perform(); BuilderInstruction instruction = manipulator.getInstruction(0); assertEquals(Opcode.INVOKE_DIRECT, instruction.getOpcode()); }