View Javadoc

1   package org.apache.commons.javaflow.bytecode.transformation.bcel.analyser;
2   
3   import org.apache.bcel.generic.Instruction;
4   import org.apache.bcel.generic.RET;
5   import org.apache.bcel.generic.JsrInstruction;
6   
7   /**
8    * List of {@link InstructionContext} that represents a sequence of an execution.
9    *
10   * <p>
11   * This object is immutable.
12   * The sequence is represented in left-associative style; that is,
13   * a sequence of [a,b,c,d] is represented as prev=[a,b,c] and last=d.
14   *
15   * @author Kohsuke Kawaguchi
16   */
17  public final class ExecutionPath {
18      /**
19       * Singleton {@link ExecutionPath} that represents an empty sequence [].
20       */
21      public static final ExecutionPath EMPTY = new ExecutionPath(null,null);
22  
23      private final ExecutionPath prev;
24      private final InstructionContext last;
25  
26      private ExecutionPath(ExecutionPath prev, InstructionContext last) {
27          this.prev = prev;
28          this.last = last;
29      }
30  
31      /**
32       * Creates a new {@link ExecutionPath} that has
33       * <tt>[... list in this ExecutionPath ..., ins]</tt>.
34       */
35      public ExecutionPath append(InstructionContext ins) {
36          return new ExecutionPath(this,ins);
37      }
38  
39      /**
40       * Returns the InstructionContextImpl with an JSR/JSR_W
41       * that was last in the ExecutionChain, without
42       * a corresponding RET, i.e.
43       * we were called by this one.
44       * Returns null if we were called from the top level.
45       */
46      public InstructionContext lastExecutionJSR(){
47          int retcount = 0;
48  
49          for( ExecutionPath ptr = this; ptr!=EMPTY; ptr=ptr.prev) {
50              Instruction i = ptr.last.getInstruction().getInstruction();
51              if (i instanceof RET) retcount++;
52              if (i instanceof JsrInstruction){
53                  retcount--;
54                  if (retcount == -1)
55                      return ptr.last;
56              }
57          }
58  
59          return null;
60      }
61  
62      /**
63       * Returns a human readable representation.
64       */
65      public String toString() {
66          if(this==EMPTY)
67              return "";
68          else {
69              return prev.toString()+"\n"+last.toString();
70          }
71      }
72  }