经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Java » 查看文章
【南大静态代码分析】作业 4:类层次结构分析与过程间常量传播
来源:cnblogs  作者:gonghr  时间:2024/1/24 10:48:54  对本文有异议

作业 4:类层次结构分析与过程间常量传播

实现类层次结构分析(CHA)

  • dispatch :根据方法调用者的类和方法签名寻找目标方法。
image-20231103155504947

比较显然,是个递归算法。

递归的终止条件有两个,一个是如果一直找不到相应方法,不断递归到父类,最后递归到 Object 在向上递归就是 nullObject 没有父类,此时返回空,说明找不到相应方法;另一个是如果当前类的方法中有能匹配方法签名的方法,并且该方法不是抽象方法,说明找到相应方法,返回该方法。

其他情况向当前类的父类递归。

  1. /**
  2. * Looks up the target method based on given class and method subsignature.
  3. *
  4. * @return the dispatched target method, or null if no satisfying method
  5. * can be found.
  6. */
  7. private JMethod dispatch(JClass jclass, Subsignature subsignature) {
  8. // TODO - finish me
  9. if (jclass == null) {
  10. return null;
  11. }
  12. if (jclass.getDeclaredMethod(subsignature) != null && !jclass.getDeclaredMethod(subsignature).isAbstract()) {
  13. return jclass.getDeclaredMethod(subsignature);
  14. }
  15. return dispatch(jclass.getSuperClass(), subsignature);
  16. }
  • resolve :通过类的继承关系确定一个调用点的所有可能的目标方法。
image-20231103160348885
  1. /**
  2. * Resolves call targets (callees) of a call site via CHA.
  3. */
  4. private Set<JMethod> resolve(Invoke callSite) {
  5. // TODO - finish me
  6. Set<JMethod> T = new HashSet<JMethod>();
  7. MethodRef m = callSite.getMethodRef();
  8. Subsignature subsignature = m.getSubsignature();
  9. JClass declaringClass = m.getDeclaringClass();
  10. CallKind callKind = CallGraphs.getCallKind(callSite);
  11. switch (callKind) {
  12. case STATIC -> {
  13. T.add(declaringClass.getDeclaredMethod(subsignature));
  14. break;
  15. }
  16. case SPECIAL -> {
  17. T.add(dispatch(declaringClass, subsignature));
  18. break;
  19. }
  20. case VIRTUAL, INTERFACE -> {
  21. ArrayDeque<JClass> subclasses = new ArrayDeque<>();
  22. HashSet<JClass> set = new HashSet<>();
  23. subclasses.addLast(declaringClass);
  24. set.add(declaringClass);
  25. while (!subclasses.isEmpty()) {
  26. JClass subclass = subclasses.pollFirst();
  27. T.add(dispatch(subclass, subsignature));
  28. for (JClass jClass : (hierarchy.getDirectSubclassesOf(subclass))) {
  29. if (!set.contains(jClass)) {
  30. set.add(jClass);
  31. subclasses.addLast(jClass);
  32. }
  33. }
  34. for (JClass jClass : (hierarchy.getDirectSubinterfacesOf(subclass))) {
  35. if (!set.contains(jClass)) {
  36. set.add(jClass);
  37. subclasses.addLast(jClass);
  38. }
  39. }
  40. for (JClass jClass : (hierarchy.getDirectImplementorsOf(subclass))) {
  41. if (!set.contains(jClass)) {
  42. set.add(jClass);
  43. subclasses.addLast(jClass);
  44. }
  45. }
  46. }
  47. break;
  48. }
  49. }
  50. return T;
  51. }
  • buildCallGraph :构造调用图
image-20231103160755879

代码中 DefaultCallGraph 既是个调用图 CG ,也能记录哪些方法访问过,即也是个 RM

  1. private CallGraph<Invoke, JMethod> buildCallGraph(JMethod entry) {
  2. DefaultCallGraph callGraph = new DefaultCallGraph();
  3. callGraph.addEntryMethod(entry);
  4. // TODO - finish me
  5. ArrayDeque<JMethod> worklist = new ArrayDeque<>();
  6. worklist.addLast(entry);
  7. while (!worklist.isEmpty()) {
  8. JMethod m = worklist.pollFirst();
  9. if (!callGraph.contains(m)) {
  10. callGraph.addReachableMethod(m);
  11. Stream<Invoke> invokeStream = callGraph.callSitesIn(m);
  12. invokeStream.forEach(cs -> {
  13. for (JMethod targetMethod : resolve(cs)) {
  14. if (targetMethod != null) {
  15. callGraph.addEdge(new Edge<>(CallGraphs.getCallKind(cs), cs, targetMethod));
  16. worklist.addLast(targetMethod);
  17. }
  18. }
  19. });
  20. }
  21. }
  22. return callGraph;
  23. }

实现过程间常量传播

  • transferCallNode
  1. @Override
  2. protected boolean transferCallNode(Stmt stmt, CPFact in, CPFact out) {
  3. // TODO - finish me
  4. return out.copyFrom(in);
  5. }
  • transferNonCallNode
  1. @Override
  2. protected boolean transferNonCallNode(Stmt stmt, CPFact in, CPFact out) {
  3. // TODO - finish me
  4. return cp.transferNode(stmt, in, out);
  5. }
  • transferNormalEdge
  1. @Override
  2. protected CPFact transferNormalEdge(NormalEdge<Stmt> edge, CPFact out) {
  3. // TODO - finish me
  4. return out;
  5. }
  • transferCallToReturnEdge
  1. @Override
  2. protected CPFact transferCallToReturnEdge(CallToReturnEdge<Stmt> edge, CPFact out) {
  3. // TODO - finish me
  4. CPFact copy = out.copy();
  5. if (edge.getSource().getDef().isPresent()) {
  6. LValue lValue = edge.getSource().getDef().get();
  7. if (lValue instanceof Var lVar) {
  8. copy.remove(lVar);
  9. }
  10. }
  11. return copy;
  12. }
  • transferCallEdge
  1. @Override
  2. protected CPFact transferCallEdge(CallEdge<Stmt> edge, CPFact callSiteOut) {
  3. // TODO - finish me
  4. CPFact newCPFact = newInitialFact();
  5. JMethod callee = edge.getCallee(); // 被调用方法
  6. Stmt source = edge.getSource();
  7. if (source instanceof Invoke invoke) {
  8. InvokeExp invokeExp = invoke.getRValue();
  9. for (int i = 0; i < invokeExp.getArgCount(); i++) {
  10. Var actual = invokeExp.getArg(i);
  11. Value value = callSiteOut.get(actual);
  12. Var formal = callee.getIR().getParam(i);
  13. newCPFact.update(formal, value);
  14. }
  15. }
  16. return newCPFact;
  17. }
  • transferReturnEdge
  1. @Override
  2. protected CPFact transferReturnEdge(ReturnEdge<Stmt> edge, CPFact returnOut) {
  3. // TODO - finish me
  4. CPFact newCPFact = newInitialFact();
  5. Stmt callSite = edge.getCallSite();
  6. if (callSite.getDef().isPresent()) {
  7. Value value = Value.getUndef(); // 返回值
  8. for (Var returnVar : edge.getReturnVars()) {
  9. value = cp.meetValue(value, returnOut.get(returnVar));
  10. }
  11. LValue lValue = callSite.getDef().get();
  12. if (lValue instanceof Var lVar) {
  13. newCPFact.update(lVar, value);
  14. }
  15. }
  16. return newCPFact;
  17. }

实现过程间 Worklist 求解器

  • initialize
  1. private void initialize() {
  2. // TODO - finish me
  3. for (Node node : icfg) {
  4. result.setInFact(node, analysis.newInitialFact());
  5. result.setOutFact(node, analysis.newInitialFact());
  6. }
  7. icfg.entryMethods().forEach(method -> {
  8. Node entryOf = icfg.getEntryOf(method);
  9. result.setOutFact(entryOf, analysis.newBoundaryFact(entryOf));
  10. result.setInFact(entryOf, analysis.newBoundaryFact(entryOf));
  11. });
  12. }
  • doSolve
  1. private void doSolve() {
  2. // TODO - finish me
  3. workList = new ArrayDeque<>();
  4. for (Node node : icfg) {
  5. workList.add(node);
  6. }
  7. while (!workList.isEmpty()) {
  8. Node node = workList.poll();
  9. for (ICFGEdge<Node> nodeICFGEdge : icfg.getInEdgesOf(node)) {
  10. analysis.meetInto(analysis.transferEdge(nodeICFGEdge, result.getOutFact(nodeICFGEdge.getSource())), result.getInFact(node));
  11. }
  12. boolean f = analysis.transferNode(node, result.getInFact(node), result.getOutFact(node));
  13. if (f) {
  14. workList.addAll(icfg.getSuccsOf(node));
  15. }
  16. }
  17. }

评测结果

原文链接:https://www.cnblogs.com/gonghr/p/17984124

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号