@Override public void visit(InvokeInstruction insn) { Expr[] exprArgs = new Expr[insn.getMethod().getParameterTypes().length]; for (int i = 0; i < insn.getArguments().size(); ++i) { exprArgs[i] = Expr.var(insn.getArguments().get(i).getIndex()); } InvocationExpr invocationExpr; if (insn.getInstance() != null) { if (insn.getType() == InvocationType.VIRTUAL) { invocationExpr = Expr.invoke(insn.getMethod(), Expr.var(insn.getInstance().getIndex()), exprArgs); } else { invocationExpr = Expr.invokeSpecial(insn.getMethod(), Expr.var(insn.getInstance().getIndex()), exprArgs); } } else { invocationExpr = Expr.invokeStatic(insn.getMethod(), exprArgs); } AssignmentStatement stmt; if (insn.getReceiver() != null) { stmt = Statement.assign(Expr.var(insn.getReceiver().getIndex()), invocationExpr); stmt.getDebugNames().addAll(insn.getReceiver().getDebugNames()); } else { stmt = Statement.assign(null, invocationExpr); } stmt.setLocation(currentLocation); stmt.setAsync(async); async = false; statements.add(stmt); }
private List<Instruction> transformSetterInvocation(InvokeInstruction insn, String property) { ValueType type = insn.getMethod().getDescriptor().parameterType(0); List<Instruction> instructions = new ArrayList<>(); if (type instanceof ValueType.Primitive) { switch (((ValueType.Primitive) type).getKind()) { case BOOLEAN: castAndSetProperty(insn, property, instructions, boolean.class); return instructions; case BYTE: castAndSetProperty(insn, property, instructions, byte.class); return instructions; case SHORT: castAndSetProperty(insn, property, instructions, short.class); return instructions; case INTEGER: castAndSetProperty(insn, property, instructions, int.class); return instructions; case FLOAT: castAndSetProperty(insn, property, instructions, float.class); return instructions; case DOUBLE: castAndSetProperty(insn, property, instructions, double.class); return instructions; case CHARACTER: case LONG: break; } } else if (type instanceof ValueType.Object) { switch (((ValueType.Object) type).getClassName()) { case "java.lang.String": { Variable castVar = insn.getProgram().createVariable(); InvokeInstruction castInvoke = new InvokeInstruction(); castInvoke.setType(InvocationType.SPECIAL); castInvoke.setMethod( new MethodReference( ResourceAccessor.class, "castFromString", String.class, Object.class)); castInvoke.getArguments().add(insn.getArguments().get(0)); castInvoke.setReceiver(castVar); instructions.add(castInvoke); setProperty(insn, property, instructions, castVar); return instructions; } default: { setProperty(insn, property, instructions, insn.getArguments().get(0)); return instructions; } } } return null; }
private void castAndSetProperty( InvokeInstruction insn, String property, List<Instruction> instructions, Class<?> primitive) { Variable castVar = program.createVariable(); InvokeInstruction castInvoke = new InvokeInstruction(); castInvoke.setType(InvocationType.SPECIAL); String primitiveCapitalized = primitive.getName(); primitiveCapitalized = Character.toUpperCase(primitiveCapitalized.charAt(0)) + primitiveCapitalized.substring(1); castInvoke.setMethod( new MethodReference( ResourceAccessor.class, "castFrom" + primitiveCapitalized, primitive, Object.class)); castInvoke.getArguments().add(insn.getArguments().get(0)); castInvoke.setReceiver(castVar); instructions.add(castInvoke); setProperty(insn, property, instructions, castVar); }
private List<Instruction> transformInvoke(InvokeInstruction insn) { if (insn.getType() != InvocationType.VIRTUAL) { return null; } MethodReference method = insn.getMethod(); if (method.getClassName().equals(ResourceArray.class.getName()) || method.getClassName().equals(ResourceMap.class.getName())) { if (method.getName().equals("keys")) { return transformKeys(insn); } InvokeInstruction accessInsn = new InvokeInstruction(); accessInsn.setType(InvocationType.SPECIAL); ValueType[] types = new ValueType[method.getDescriptor().parameterCount() + 2]; types[0] = ValueType.object("java.lang.Object"); System.arraycopy( method.getDescriptor().getSignature(), 0, types, 1, method.getDescriptor().parameterCount() + 1); accessInsn.setMethod( new MethodReference(ResourceAccessor.class.getName(), method.getName(), types)); accessInsn.getArguments().add(insn.getInstance()); accessInsn.getArguments().addAll(insn.getArguments()); accessInsn.setReceiver(insn.getReceiver()); return Arrays.asList(accessInsn); } ClassReader iface = innerSource.get(method.getClassName()); if (iface == null || !innerSource.isSuperType(Resource.class.getName(), iface.getName()).orElse(false)) { return null; } if (method.getName().startsWith("get")) { if (method.getName().length() > 3) { return transformGetterInvocation(insn, getPropertyName(method.getName().substring(3))); } } else if (method.getName().startsWith("is")) { if (method.getName().length() > 2) { return transformGetterInvocation(insn, getPropertyName(method.getName().substring(2))); } } else if (method.getName().startsWith("set")) { if (method.getName().length() > 3) { return transformSetterInvocation(insn, getPropertyName(method.getName().substring(3))); } } return null; }
private void setProperty( InvokeInstruction insn, String property, List<Instruction> instructions, Variable valueVar) { Variable nameVar = program.createVariable(); StringConstantInstruction nameInsn = new StringConstantInstruction(); nameInsn.setConstant(property); nameInsn.setReceiver(nameVar); instructions.add(nameInsn); InvokeInstruction accessorInvoke = new InvokeInstruction(); accessorInvoke.setType(InvocationType.SPECIAL); accessorInvoke.setMethod( new MethodReference( ResourceAccessor.class, "put", Object.class, String.class, Object.class, void.class)); accessorInvoke.getArguments().add(insn.getInstance()); accessorInvoke.getArguments().add(nameVar); accessorInvoke.getArguments().add(valueVar); instructions.add(accessorInvoke); }
@Override public void visit(InvokeInstruction insn) { if (insn.getInstance() != null) { escaping[insn.getInstance().getIndex()] = true; } for (Variable arg : insn.getArguments()) { escaping[arg.getIndex()] = true; } }
private List<Instruction> transformKeys(InvokeInstruction insn) { Variable tmp = program.createVariable(); InvokeInstruction keysInsn = new InvokeInstruction(); keysInsn.setType(InvocationType.SPECIAL); keysInsn.setMethod( new MethodReference(ResourceAccessor.class, "keys", Object.class, Object.class)); keysInsn.getArguments().add(insn.getInstance()); keysInsn.setReceiver(tmp); InvokeInstruction transformInsn = new InvokeInstruction(); transformInsn.setType(InvocationType.SPECIAL); transformInsn.setMethod( new MethodReference(ResourceAccessor.class, "keysToStrings", Object.class, String[].class)); transformInsn.getArguments().add(tmp); transformInsn.setReceiver(insn.getReceiver()); return Arrays.asList(keysInsn, transformInsn); }