001 package serp.bytecode; 002 003 import java.io.*; 004 import java.util.*; 005 006 import serp.bytecode.lowlevel.*; 007 import serp.bytecode.visitor.*; 008 009 /** 010 * A line number corresponds to a sequence of opcodes that map logically 011 * to a line of source code. 012 * 013 * @author Abe White 014 */ 015 public class LineNumber implements Comparable, InstructionPtr, BCEntity, 016 VisitAcceptor { 017 private int _line = 0; 018 private LineNumberTable _owner = null; 019 InstructionPtrStrategy _target = new InstructionPtrStrategy(this); 020 021 LineNumber(LineNumberTable owner) { 022 _owner = owner; 023 } 024 025 LineNumber(LineNumberTable owner, int startPc) { 026 this(owner); 027 setStartPc(startPc); 028 } 029 030 /** 031 * Line numbers are stored in a {@link LineNumberTable}. 032 */ 033 public LineNumberTable getTable() { 034 return _owner; 035 } 036 037 void invalidate() { 038 _owner = null; 039 } 040 041 /** 042 * Return source line number. 043 */ 044 public int getLine() { 045 return _line; 046 } 047 048 /** 049 * Set the source line number. 050 */ 051 public void setLine(int lineNumber) { 052 _line = lineNumber; 053 } 054 055 /** 056 * Return the instruction marking the beginning of this line. 057 */ 058 public Instruction getStart() { 059 return _target.getTargetInstruction(); 060 } 061 062 /** 063 * Return the index into the code byte array at which this line starts. 064 */ 065 public int getStartPc() { 066 return _target.getByteIndex(); 067 } 068 069 /** 070 * Set the index into the code byte array at which this line starts. 071 */ 072 public void setStartPc(int startPc) { 073 _target.setByteIndex(startPc); 074 } 075 076 /** 077 * Set the {@link Instruction} marking the beginning this line. 078 * The instruction must already be a part of the method. 079 */ 080 public void setStart(Instruction instruction) { 081 _target.setTargetInstruction(instruction); 082 } 083 084 public void updateTargets() { 085 _target.updateTargets(); 086 } 087 088 public void replaceTarget(Instruction oldTarget, Instruction newTarget) { 089 _target.replaceTarget(oldTarget, newTarget); 090 } 091 092 public Project getProject() { 093 return _owner.getProject(); 094 } 095 096 public ConstantPool getPool() { 097 return _owner.getPool(); 098 } 099 100 public ClassLoader getClassLoader() { 101 return _owner.getClassLoader(); 102 } 103 104 public boolean isValid() { 105 return _owner != null; 106 } 107 108 public void acceptVisit(BCVisitor visit) { 109 visit.enterLineNumber(this); 110 visit.exitLineNumber(this); 111 } 112 113 public int compareTo(Object other) { 114 if (!(other instanceof LineNumber)) 115 return -1; 116 117 LineNumber ln = (LineNumber) other; 118 if (getStartPc() == ln.getStartPc()) 119 return 0; 120 if (getStartPc() < ln.getStartPc()) 121 return -1; 122 return 1; 123 } 124 125 void read(DataInput in) throws IOException { 126 setStartPc(in.readUnsignedShort()); 127 setLine(in.readUnsignedShort()); 128 } 129 130 void write(DataOutput out) throws IOException { 131 out.writeShort(getStartPc()); 132 out.writeShort(getLine()); 133 } 134 135 public Code getCode() { 136 return _owner.getCode(); 137 } 138 }