@Nonnull private BuilderInstruction21c newBuilderInstruction21c(@Nonnull Instruction21c instruction) { return new BuilderInstruction21c( instruction.getOpcode(), instruction.getRegisterA(), convertReference(instruction.getReference())); }
private void testForExpectedInstruction(String register0, String expectedClassName) { ExecutionGraphManipulator manipulator = getOptimizedGraph(METHOD_NAME, 0, register0, "Ljava/lang/String;"); BuilderInstruction21c instruction = (BuilderInstruction21c) manipulator.getInstruction(ADDRESS); assertEquals(Opcode.CONST_CLASS, instruction.getOpcode()); assertEquals(0, instruction.getRegisterA()); String actualClassName = ReferenceUtil.getReferenceString(instruction.getReference()); assertEquals(expectedClassName, actualClassName); } }
int registerA = original.getRegisterA(); String referenceType = ReferenceUtil.getReferenceString(original.getReference()); if (!preCastType.equals(referenceType)) {
@Override protected BuilderInstruction getRealInsn0(LabelAssigner assigner) { return new BuilderInstruction21c(opc, (short) getRegA().getNumber(), referencedItem); }
private void testForExpectedInstruction(Object register1, String expectedConstant) { VirtualType instanceType = vm.getClassManager().getVirtualType("Ljava/lang/String;"); ExecutionGraphManipulator manipulator = getOptimizedGraph(METHOD_NAME, 0, new UninitializedInstance(instanceType), "Ljava/lang/String;", 1, register1, "[B"); BuilderInstruction21c instruction = (BuilderInstruction21c) manipulator.getInstruction (ADDRESS); assertEquals(Opcode.CONST_STRING, instruction.getOpcode()); assertEquals(0, instruction.getRegisterA()); String actualConstant = ((StringReference) instruction.getReference()).getString(); assertEquals(expectedConstant, actualConstant); } }
private List<BuilderInstruction> getArrayAccessorInstructions(int arrayRegister, List<Integer> registers, List<String> parameterTypes) { List<BuilderInstruction> instructions = new LinkedList<>(); for (int index = 0; index < parameterTypes.size(); index++) { int register = registers.get(index); BuilderInstruction constInstruction = ConstantBuilder.buildConstant(index, register); BuilderInstruction arrayGet = new BuilderInstruction23x(Opcode.AGET_OBJECT, register, arrayRegister, register); String typeName = parameterTypes.get(index); if (ClassNameUtils.isPrimitive(typeName)) { // check-cast expects a non-primitive type (afaik) typeName = ClassNameUtils.binaryToInternal(ClassNameUtils.getWrapper(typeName)); } BuilderTypeReference typeRef = manipulator.getDexBuilder().internTypeReference(typeName); BuilderInstruction checkCast = new BuilderInstruction21c(Opcode.CHECK_CAST, register, typeRef); instructions.add(constInstruction); instructions.add(arrayGet); instructions.add(checkCast); } return instructions; }
@Test public void thisReferencedWithInvokeIsCorrectlyOptimizedAsConstClass() { String methodName = "invokeGetClassOnThis()V"; ExecutionGraphManipulator manipulator = getOptimizedGraph(vm, methodName, 1, new UninitializedInstance(thisReference), CLASS_NAME); assertEquals(BuilderInstruction21c.class, manipulator.getInstruction(ADDRESS).getClass()); BuilderInstruction21c instruction = (BuilderInstruction21c) manipulator.getInstruction(ADDRESS); assertEquals(Opcode.CONST_CLASS, instruction.getOpcode()); assertEquals(0, instruction.getRegisterA()); String actualClassName = ReferenceUtil.getReferenceString(instruction.getReference()); assertEquals(CLASS_NAME, actualClassName); }
BuilderInstruction buildClassForNameReplacement(int address) { InvokeOp op = (InvokeOp) manipulator.getOp(address); int[] parameterRegisters = op.getParameterRegisters(); int register = parameterRegisters[0]; String javaClassName = (String) manipulator.getRegisterConsensusValue(address, register); String smaliClassName = ClassNameUtils.binaryToInternal(javaClassName); HeapItem klazz = manipulator.getRegisterConsensus(address, MethodState.ResultRegister); if (klazz == null) { log.warn("Optimizing Class.forName of potentially non-existent class: {}", smaliClassName); } BuilderTypeReference classRef = manipulator.getDexBuilder().internTypeReference(smaliClassName); BuilderInstruction constClassInstruction = new BuilderInstruction21c(Opcode.CONST_CLASS, register, classRef); return constClassInstruction; }
@Test public void thisReferencedWithInvokeRangeIsCorrectlyOptimizedAsConstClass() { String methodName = "invokeRangeGetClassOnThis()V"; ExecutionGraphManipulator manipulator = getOptimizedGraph(vm, methodName, 1, new UninitializedInstance(thisReference), CLASS_NAME); assertEquals(BuilderInstruction21c.class, manipulator.getInstruction(ADDRESS).getClass()); BuilderInstruction21c instruction = (BuilderInstruction21c) manipulator.getInstruction(ADDRESS); assertEquals(Opcode.CONST_CLASS, instruction.getOpcode()); assertEquals(0, instruction.getRegisterA()); String actualClassName = ReferenceUtil.getReferenceString(instruction.getReference()); assertEquals(CLASS_NAME, actualClassName); } }
@Test public void withString() { String value = "Ever sift sand through a screen?"; StringReference stringRef = dexBuilder.internStringReference(value); Instruction expected = new BuilderInstruction21c(Opcode.CONST_STRING, REGISTER, stringRef); Instruction actual = ConstantBuilder.buildConstant(value, "Ljava/lang/String;", REGISTER, dexBuilder); testEquals(expected, actual); } }
replacement = new BuilderInstruction21c(newOp, destRegister, fieldRef); } else { replacement = new BuilderInstruction22c(newOp, destRegister, targetRegister, fieldRef);
@Test public void withClass() { Class<?> value = String.class; String className = ClassNameUtils.toInternal(value); TypeReference typeRef = dexBuilder.internTypeReference(className); Instruction expected = new BuilderInstruction21c(Opcode.CONST_CLASS, REGISTER, typeRef); Instruction actual = ConstantBuilder.buildConstant(value, "Ljava/lang/Class;", REGISTER, dexBuilder); testEquals(expected, actual); }
BuilderInstruction buildUninitializedInstanceReferenceResultReplacement(int address) { InvokeOp invokeOp = (InvokeOp) manipulator.getOp(address); int instanceRegister = invokeOp.getParameterRegisters()[0]; HeapItem item = manipulator.getRegisterConsensus(address, instanceRegister); BuilderInstruction original = manipulator.getInstruction(address); int nextAddress = address + original.getCodeUnits(); MoveOp moveOp = (MoveOp) manipulator.getOp(nextAddress); int destRegsiter = moveOp.getToRegister(); ReferenceInstruction instr = (ReferenceInstruction) original; String methodDescriptor = ReferenceUtil.getReferenceString(instr.getReference()); BuilderInstruction replacementInstruction = null; if (methodDescriptor.equals(OBJECT_GET_CLASS_SIGNATURE)) { String smaliClassName = item.getType(); BuilderTypeReference classRef = manipulator.getDexBuilder().internTypeReference(smaliClassName); replacementInstruction = new BuilderInstruction21c(Opcode.CONST_CLASS, destRegsiter, classRef); } return replacementInstruction; }
case "Ljava/lang/String;": BuilderStringReference stringRef = dexBuilder.internStringReference(value.toString()); constant = new BuilderInstruction21c(Opcode.CONST_STRING, register, stringRef); break; case "Ljava/lang/Class;": String className = ClassNameUtils.toInternal(klazz); BuilderTypeReference typeRef = dexBuilder.internTypeReference(className); constant = new BuilderInstruction21c(Opcode.CONST_CLASS, register, typeRef); break; default:
short regA = parseRegister_byte((REGISTER138!=null?REGISTER138.getText():null)); method_stack.peek().methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA, dexBuilder.internTypeReference((nonvoid_type_descriptor139!=null?((smaliTreeWalker.nonvoid_type_descriptor_return)nonvoid_type_descriptor139).type:null))));
short regA = parseRegister_byte((REGISTER135!=null?REGISTER135.getText():null)); method_stack.peek().methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA, dexBuilder.internStringReference(string_literal136)));
method_stack.peek().methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA, dexBuilder.internFieldReference(fieldReference)));
method_stack.peek().methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA, dexBuilder.internMethodHandle(methodHandleReference)));
method_stack.peek().methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA, dexBuilder.internMethodProtoReference(methodProtoReference)));
@Nonnull private BuilderInstruction21c newBuilderInstruction21c(@Nonnull Instruction21c instruction) { return new BuilderInstruction21c( instruction.getOpcode(), instruction.getRegisterA(), instruction.getReference()); }