1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
/* FJBG -- Fast Java Bytecode Generator
* Copyright 2002-2013 LAMP/EPFL
* @author Michel Schinz
*/
package ch.epfl.lamp.fjbg;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
/**
* Attribute storing correspondance between instructions and source
* line numbers.
*
* @author Michel Schinz
* @version 1.0
*/
public class JLineNumberTableAttribute extends JAttribute {
protected final JCode code;
public JLineNumberTableAttribute(FJBGContext context,
JClass clazz,
JCode owner) {
super(context, clazz);
this.code = owner;
assert owner.getOwner().getOwner() == clazz;
}
public JLineNumberTableAttribute(FJBGContext context,
JClass clazz,
Object owner,
String name,
int size,
DataInputStream stream)
throws IOException {
super(context, clazz, name);
this.code = (JCode)owner;
int[] mapping = new int[code.getSize()];
int count = stream.readShort();
for (int i = 0; i < count; ++i) {
int startPC = stream.readShort();
int lineNum = stream.readShort();
mapping[startPC] = lineNum;
}
// Avoids duplication of LineNumberTable attribute
// (see method ensureLineNumberCapacity in class JCode).
assert code.lineNumbers == null;
code.lineNumbers = new int[0];
int lineNum = 0;
for (int pc = 0; pc < mapping.length; ++pc) {
if (mapping[pc] != 0) lineNum = mapping[pc];
if (lineNum != 0) code.setLineNumber(pc, lineNum);
}
assert name.equals(getName());
}
public String getName() { return "LineNumberTable"; }
// Follows javap output format for LineNumberTable attribute.
/*@Override*/ public String toString() {
StringBuffer buf = new StringBuffer(" LineNumberTable: ");
int[] encoding = encode();
for (int i = 0; i < encoding.length/2; ++i) {
buf.append("\n line ");
buf.append(encoding[i * 2 + 1]);
buf.append(": ");
buf.append(encoding[i * 2]);
}
buf.append("\n");
return buf.toString();
}
protected int[] encoding;
protected int[] encode() {
if (encoding == null) {
int[] lineNumbers = code.getLineNumbers();
int[] preEncoding = new int[lineNumbers.length * 2];
int prevLineNum = 0;
int i = 0;
for (int pc = 0; pc < lineNumbers.length; ++pc) {
int lineNum = lineNumbers[pc];
if (lineNum != 0 & lineNum != prevLineNum) {
preEncoding[i++] = pc;
preEncoding[i++] = lineNum;
prevLineNum = lineNum;
}
}
if (i == preEncoding.length)
encoding = preEncoding;
else {
encoding = new int[i];
System.arraycopy(preEncoding, 0, encoding, 0, i);
}
}
return encoding;
}
protected int getSize() {
int[] encoding = encode();
return 2 + encoding.length * 2;
}
protected void writeContentsTo(DataOutputStream stream) throws IOException {
int[] encoding = encode();
int entries = encoding.length / 2;
stream.writeShort(entries);
for (int i = 0; i < entries; ++i) {
stream.writeShort(encoding[i * 2]);
stream.writeShort(encoding[i * 2 + 1]);
}
}
}
|