private void applyParametersToWriteStats(ReadWriteStatsBuilder stats, MethodReference method) { for (int i = 0; i <= method.parameterCount(); ++i) { stats.writes[i]++; } }
public int getMetaParameterCount() { return (isStatic ? 0 : 1) + method.parameterCount(); }
private MethodReference getAsyncReference(MethodReference methodRef) { ValueType[] signature = new ValueType[methodRef.parameterCount() + 2]; for (int i = 0; i < methodRef.parameterCount(); ++i) { signature[i] = methodRef.getDescriptor().parameterType(i); } signature[methodRef.parameterCount()] = ValueType.parse(AsyncCallback.class); signature[methodRef.parameterCount() + 1] = ValueType.VOID; return new MethodReference(methodRef.getClassName(), methodRef.getName(), signature); }
@Override public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { function(context, writer, "Math." + methodRef.getName(), methodRef.parameterCount()); }
private Method asJvmMethod(MethodReference method) { Class<?> cls; try { cls = Class.forName(method.getClassName(), false, classLoader); } catch (ClassNotFoundException e) { throw new RuntimeException("Can't find class " + method.getClassName()); } Class<?>[] jvmParameters = new Class[method.parameterCount()]; for (int i = 0; i < method.parameterCount(); ++i) { jvmParameters[i] = asJvmClass(method.parameterType(i)); } Class<?> jvmReturnType = asJvmClass(method.getReturnType()); for (Method jvmMethod : cls.getDeclaredMethods()) { if (Arrays.equals(jvmMethod.getParameterTypes(), jvmParameters) && jvmReturnType.equals(jvmMethod.getReturnType())) { return jvmMethod; } } throw new RuntimeException("Method not found: " + method); }
private Method getJavaMethod(ClassLoader classLoader, MethodReference ref) throws ReflectiveOperationException { Class<?> cls = Class.forName(ref.getClassName(), true, classLoader); Class<?>[] parameterTypes = new Class<?>[ref.parameterCount()]; for (int i = 0; i < parameterTypes.length; ++i) { parameterTypes[i] = getJavaType(classLoader, ref.parameterType(i)); } return cls.getDeclaredMethod(ref.getName(), parameterTypes); }
public ExceptionHandlingShadowStackContributor(Characteristics characteristics, List<CallSiteDescriptor> callSites, MethodReference method, Program program) { this.characteristics = characteristics; this.callSites = callSites; this.method = method; this.program = program; Graph cfg = ProgramUtils.buildControlFlowGraph(program); dom = GraphUtils.buildDominatorTree(cfg); variableDefinitionPlaces = ProgramUtils.getVariableDefinitionPlaces(program); parameterCount = method.parameterCount() + 1; }
private Variable unwrapSingleDimensionArray(CallLocation location, Variable var, ValueType type) { Variable result = program.createVariable(); InvokeInstruction insn = new InvokeInstruction(); insn.setMethod(singleDimensionArrayUnwrapper(type)); insn.setType(InvocationType.SPECIAL); List<Variable> args = new ArrayList<>(); if (insn.getMethod().parameterCount() == 2) { Variable cls = program.createVariable(); ClassConstantInstruction clsInsn = new ClassConstantInstruction(); clsInsn.setConstant(type); clsInsn.setLocation(location.getSourceLocation()); clsInsn.setReceiver(cls); replacement.add(clsInsn); args.add(cls); } args.add(var); insn.setArguments(args.toArray(new Variable[0])); insn.setReceiver(result); replacement.add(insn); return result; }
@Override public boolean canHandle(MethodReference method) { if (!characteristics.isStructure(method.getClassName())) { return false; } switch (method.getName()) { case "cast": case "toAddress": return method.parameterCount() == 0; case "sizeOf": return method.parameterCount() == 1 && method.parameterType(0).equals(ValueType.parse(Class.class)); case "add": return method.parameterCount() == 3 && method.parameterType(0).equals(ValueType.parse(Class.class)) && method.parameterType(1).equals(ValueType.parse(Structure.class)) && method.parameterType(2).equals(ValueType.INTEGER); default: return false; } }
private void generateLocals(RegularMethodNode methodNode, int[] temporaryCount) { int start = methodNode.getReference().parameterCount() + 1; for (int i = start; i < methodNode.getVariables().size(); ++i) { VariableNode variableNode = methodNode.getVariables().get(i); if (variableNode.getType() == null) { continue; } localsWriter.printType(variableNode.getType()).print(" local_").print(String.valueOf(i)).println(";"); } for (CVariableType type : CVariableType.values()) { for (int i = 0; i < temporaryCount[type.ordinal()]; ++i) { localsWriter.print(type.text + " tmp_" + type.name().toLowerCase() + "_" + i).println(";"); } } } }
public void transformProgram(Program program, MethodReference methodReference) { if (!characteristics.isManaged(methodReference)) { return; } InsertionVisitor visitor = new InsertionVisitor(); for (BasicBlock block : program.getBasicBlocks()) { for (Instruction instruction : block) { instruction.acceptVisitor(visitor); } } if (visitor.changed) { new PhiUpdater().updatePhis(program, methodReference.parameterCount() + 1); } }
public void apply(Program program, MethodReference methodReference) { this.program = program; findVarClasses(); findConstantVariables(); findSafeArrays(); removeSafeArrays(); if (hasModifications) { Variable[] parameters = new Variable[methodReference.parameterCount() + 1]; for (int i = 0; i < parameters.length; ++i) { parameters[i] = program.variableAt(i); } new PhiUpdater().updatePhis(program, parameters); } }
@Override public void invoke(VariableReader receiver, VariableReader instance, MethodReference method, List<? extends VariableReader> arguments, InvocationType type) { if (instance == null) { invokeSpecial(receiver, null, method, arguments); } else { switch (type) { case SPECIAL: invokeSpecial(receiver, instance, method, arguments); break; case VIRTUAL: invokeVirtual(receiver, instance, method, arguments); break; } if (method.getName().equals("getClass") && method.parameterCount() == 0 && method.getReturnType().isObject(Class.class) && receiver != null) { getNode(instance).connect(getNode(receiver).getClassValueNode()); } } }
@Override public void apply(IntrinsicContext context, InvocationExpr invocation) { MethodReference method = invocation.getMethod(); if (method.getClassName().equals(Function.class.getName())) { generateGetFunction(context, invocation); return; } context.writer().print("(((").printType(method.getReturnType()).print(" (*)("); if (method.parameterCount() > 0) { context.writer().printType(method.parameterType(0)); for (int i = 1; i < method.parameterCount(); ++i) { context.writer().print(", ").printType(method.parameterType(i)); } } context.writer().print(")) "); context.emit(invocation.getArguments().get(0)); context.writer().print(")("); if (invocation.getArguments().size() > 1) { context.emit(invocation.getArguments().get(1)); for (int i = 2; i < invocation.getArguments().size(); ++i) { context.writer().print(", "); context.emit(invocation.getArguments().get(i)); } } context.writer().print("))"); }
public void optimize(RegularMethodNode method, Program program, boolean friendlyToDebugger) { ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size()); stats.analyze(program); applyParametersToWriteStats(stats, method.getReference()); boolean[] preservedVars = new boolean[stats.writes.length]; BreakEliminator breakEliminator = new BreakEliminator(); breakEliminator.eliminate(method.getBody()); if (friendlyToDebugger) { for (int i = 0; i < method.getVariables().size(); ++i) { if (method.getVariables().get(i).getName() != null) { preservedVars[i] = true; } } } OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, stats.writes, stats.reads, moveConstants ? stats.constants : new Object[stats.constants.length], friendlyToDebugger); method.getBody().acceptVisitor(optimizer); method.setBody(optimizer.resultStmt); int paramCount = method.getReference().parameterCount(); UnusedVariableEliminator unusedEliminator = new UnusedVariableEliminator(paramCount, method.getVariables()); method.getBody().acceptVisitor(unusedEliminator); method.getVariables().clear(); method.getVariables().addAll(unusedEliminator.getReorderedVariables()); method.getBody().acceptVisitor(new RedundantLabelEliminator()); method.getBody().acceptVisitor(new RedundantReturnElimination()); for (int i = 0; i < method.getVariables().size(); ++i) { method.getVariables().get(i).setIndex(i); } }
@Override public void methodReached(DependencyAgent agent, MethodDependency method) { switch (method.getReference().getName()) { case "invoke": case "instantiate": case "function": if (reachedFunctorMethods.add(method.getReference()) && !method.isMissing()) { for (int i = 0; i < method.getReference().parameterCount(); ++i) { DependencyNode node = method.getVariable(i); if (functorParamNodes.add(node)) { node.addConsumer(type -> { if (agent.getClassHierarchy().isSuperType(method.getMethod().getOwnerName(), type.getName(), false)) { reachFunctorMethods(agent, type.getName()); } }); } } } break; case "unwrapString": method.getResult().propagate(agent.getType("java.lang.String")); break; } }
private void emitVirtualDeclaration(MethodReference ref) throws IOException { String methodName = naming.getNameFor(ref.getDescriptor()); writer.append("\"").append(methodName).append("\""); writer.append(",").ws().append("function("); List<String> args = new ArrayList<>(); for (int i = 1; i <= ref.parameterCount(); ++i) { args.add(variableNameForInitializer(i)); } for (int i = 0; i < args.size(); ++i) { if (i > 0) { writer.append(",").ws(); } writer.append(args.get(i)); } writer.append(")").ws().append("{").ws(); if (ref.getDescriptor().getResultType() != ValueType.VOID) { writer.append("return "); } writer.appendMethodBody(ref).append("("); writer.append("this"); for (String arg : args) { writer.append(",").ws().append(arg); } writer.append(");").ws().append("}"); }
public void analyze(Program program, MethodReference methodReference) { InstructionEscapeVisitor visitor = new InstructionEscapeVisitor(program.variableCount()); for (int i = 0; i <= methodReference.parameterCount(); ++i) { visitor.escapingVars[i] = true; } for (BasicBlock block : program.getBasicBlocks()) { for (Instruction insn : block) { insn.acceptVisitor(visitor); } if (block.getExceptionVariable() != null) { visitor.escapingVars[block.getExceptionVariable().getIndex()] = true; } } definitionClasses = visitor.definitionClasses.pack(program.variableCount()); escapingVars = new boolean[program.variableCount()]; fieldTypes = visitor.fieldTypes; for (int i = 0; i < program.variableCount(); ++i) { if (visitor.escapingVars[i]) { escapingVars[definitionClasses[i]] = true; } } analyzePhis(program); propagateFields(program, visitor.fields); fields = packFields(visitor.fields); }
public ValueEmitter invoke(MethodReference method, ValueEmitter... arguments) { for (int i = 0; i < method.parameterCount(); ++i) { if (!hierarchy.isSuperType(method.parameterType(i), arguments[i].getType(), true)) { throw new EmitException("Argument " + i + " of type " + arguments[i].getType() + " is " + "not compatible with method " + method); } } Variable result = null; if (method.getReturnType() != ValueType.VOID) { result = program.createVariable(); } InvokeInstruction insn = new InvokeInstruction(); insn.setType(InvocationType.SPECIAL); insn.setMethod(method); insn.setReceiver(result); Variable[] insnArguments = new Variable[arguments.length]; for (int i = 0; i < insnArguments.length; ++i) { insnArguments[i] = arguments[i].variable; } insn.setArguments(insnArguments); addInstruction(insn); return result != null ? var(result, method.getReturnType()) : null; }
@Override public void methodReached(DependencyAgent agent, MethodDependency method) { MethodReference ref = method.getReference(); MethodReference asyncRef = getAsyncReference(ref); MethodDependency asyncMethod = agent.linkMethod(asyncRef); method.addLocationListener(asyncMethod::addLocation); int paramCount = ref.parameterCount(); for (int i = 0; i <= paramCount; ++i) { method.getVariable(i).connect(asyncMethod.getVariable(i)); } asyncMethod.getVariable(paramCount + 1).propagate(agent.getType(AsyncCallbackWrapper.class.getName())); MethodDependency completeMethod = agent.linkMethod( new MethodReference(AsyncCallbackWrapper.class, "complete", Object.class, void.class)); if (method.getResult() != null) { completeMethod.getVariable(1).connect(method.getResult(), type -> agent.getClassHierarchy() .isSuperType(ref.getReturnType(), ValueType.object(type.getName()), false)); } completeMethod.use(); MethodDependency errorMethod = agent.linkMethod(new MethodReference(AsyncCallbackWrapper.class, "error", Throwable.class, void.class)); errorMethod.getVariable(1).connect(method.getThrown()); errorMethod.use(); agent.linkMethod(new MethodReference(AsyncCallbackWrapper.class, "create", AsyncCallback.class, AsyncCallbackWrapper.class)).use(); asyncMethod.use(); }