Skip to content

Commit c077c02

Browse files
Code cleanup, Add comments
1 parent 06c55cc commit c077c02

File tree

21 files changed

+939
-228
lines changed

21 files changed

+939
-228
lines changed

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ClassEntry.java

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,17 +99,33 @@ private void addFile(FileEntry addFileEntry) {
9999
}
100100
}
101101

102+
/**
103+
* Add a field to the class entry and store its file entry.
104+
*
105+
* @param field the {@code FieldEntry} to add
106+
*/
102107
@Override
103108
public void addField(FieldEntry field) {
104109
addFile(field.getFileEntry());
105110
super.addField(field);
106111
}
107112

113+
/**
114+
* Add a method to the class entry and store its file entry.
115+
*
116+
* @param methodEntry the {@code MethodEntry} to add
117+
*/
108118
public void addMethod(MethodEntry methodEntry) {
109119
addFile(methodEntry.getFileEntry());
110120
methods.add(methodEntry);
111121
}
112122

123+
/**
124+
* Add a compiled method to the class entry and store its file entry and the file entries of
125+
* inlined methods.
126+
*
127+
* @param compiledMethodEntry the {@code CompiledMethodEntry} to add
128+
*/
113129
public void addCompiledMethod(CompiledMethodEntry compiledMethodEntry) {
114130
addFile(compiledMethodEntry.primary().getFileEntry());
115131
for (Range range : compiledMethodEntry.topDownRangeStream().toList()) {
@@ -156,6 +172,18 @@ public int getFileIdx() {
156172
return getFileIdx(this.getFileEntry());
157173
}
158174

175+
/**
176+
* Returns the file index of a given file entry within this class entry.
177+
*
178+
* <p>
179+
* The first time a file entry is fetched, this produces a file index that is used for further
180+
* index lookups. The file index is only created once. Therefore, this method must be used only
181+
* after debug info generation is finished and no more file entries can be added to this class
182+
* entry.
183+
*
184+
* @param file the given file entry
185+
* @return the index of the file entry
186+
*/
159187
public int getFileIdx(FileEntry file) {
160188
if (file == null || files.isEmpty() || !files.contains(file)) {
161189
return 0;
@@ -173,7 +201,7 @@ public int getFileIdx(FileEntry file) {
173201
return indexedFiles.get(file);
174202
}
175203

176-
public DirEntry getDirEntry(FileEntry file) {
204+
private DirEntry getDirEntry(FileEntry file) {
177205
if (file == null) {
178206
return null;
179207
}
@@ -185,6 +213,18 @@ public int getDirIdx(FileEntry file) {
185213
return getDirIdx(dirEntry);
186214
}
187215

216+
/**
217+
* Returns the dir index of a given dir entry within this class entry.
218+
*
219+
* <p>
220+
* The first time a dir entry is fetched, this produces a dir index that is used for further
221+
* index lookups. The dir index is only created once. Therefore, this method must be used only
222+
* after debug info generation is finished and no more dir entries can be added to this class
223+
* entry.
224+
*
225+
* @param dir the given dir entry
226+
* @return the index of the dir entry
227+
*/
188228
public int getDirIdx(DirEntry dir) {
189229
if (dir == null || dir.getPathString().isEmpty() || dirs.isEmpty() || !dirs.contains(dir)) {
190230
return 0;
@@ -251,20 +291,20 @@ public long hipc() {
251291
}
252292

253293
/**
254-
* Retrieve a stream of all files referenced from debug info for this class in line info file
294+
* Retrieve a list of all files referenced from debug info for this class in line info file
255295
* table order, starting with the file at index 1.
256296
*
257-
* @return a stream of all referenced files
297+
* @return a list of all referenced files
258298
*/
259299
public List<FileEntry> getFiles() {
260300
return List.copyOf(files);
261301
}
262302

263303
/**
264-
* Retrieve a stream of all directories referenced from debug info for this class in line info
304+
* Retrieve a list of all directories referenced from debug info for this class in line info
265305
* directory table order, starting with the directory at index 1.
266306
*
267-
* @return a stream of all referenced directories
307+
* @return a list of all referenced directories
268308
*/
269309
public List<DirEntry> getDirs() {
270310
return List.copyOf(dirs);

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/CompiledMethodEntry.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public record CompiledMethodEntry(PrimaryRange primary, List<FrameSizeChangeEntr
4747
* Returns a stream that traverses all the callees of the method associated with this entry. The
4848
* stream performs a depth-first pre-order traversal of the call tree.
4949
*
50-
* @return the iterator
50+
* @return the stream of all ranges
5151
*/
5252
public Stream<Range> topDownRangeStream() {
5353
// skip the root of the range stream which is the primary range
@@ -59,7 +59,7 @@ public Stream<Range> topDownRangeStream() {
5959
* returns only the leafs. The stream performs a depth-first pre-order traversal of the call
6060
* tree returning only ranges with no callees.
6161
*
62-
* @return the iterator
62+
* @return the stream of leaf ranges
6363
*/
6464
public Stream<Range> leafRangeStream() {
6565
return topDownRangeStream().filter(Range::isLeaf);
@@ -70,7 +70,7 @@ public Stream<Range> leafRangeStream() {
7070
* returns only the call ranges. The stream performs a depth-first pre-order traversal of the
7171
* call tree returning only ranges with callees.
7272
*
73-
* @return the iterator
73+
* @return the stream of call ranges
7474
*/
7575
public Stream<Range> callRangeStream() {
7676
return topDownRangeStream().filter(range -> !range.isLeaf());

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/DebugInfoBase.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -155,20 +155,20 @@ public abstract class DebugInfoBase {
155155
*/
156156
private ClassEntry hubClassEntry;
157157

158-
/*
158+
/**
159159
* A prefix used to label indirect types used to ensure gdb performs oop reference --> raw
160-
* address translation
160+
* address translation.
161161
*/
162162
public static final String COMPRESSED_PREFIX = "_z_.";
163-
/*
163+
/**
164164
* A prefix used for type signature generation to generate unique type signatures for type
165-
* layout type units
165+
* layout type units.
166166
*/
167167
public static final String LAYOUT_PREFIX = "_layout_.";
168168

169-
/*
169+
/**
170170
* The name of the type for header field hub which needs special case processing to remove tag
171-
* bits
171+
* bits.
172172
*/
173173
public static final String HUB_TYPE_NAME = "java.lang.Class";
174174

@@ -230,9 +230,10 @@ public void installDebugInfo(DebugInfoProvider debugInfoProvider) {
230230
/* Reference alignment must be 8 bytes. */
231231
assert objectAlignment == 8;
232232

233-
stringTable = debugInfoProvider.getStringTable();
234-
235-
// Create the cachePath string entry which serves as base directory for source files
233+
stringTable = new StringTable();
234+
/* Ensure we have a null string at the start of the string table. */
235+
uniqueDebugString("");
236+
/* Create the cachePath string entry which serves as base directory for source files */
236237
cachePath = uniqueDebugString(debugInfoProvider.cachePath());
237238

238239
compiledMethods.addAll(debugInfoProvider.compiledMethodEntries());

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/LocalEntry.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,28 @@
2525

2626
package com.oracle.objectfile.debugentry;
2727

28-
public record LocalEntry(String name, TypeEntry type, int slot, int line) {
28+
import java.util.concurrent.atomic.AtomicInteger;
29+
30+
public record LocalEntry(String name, TypeEntry type, int slot, AtomicInteger line) {
31+
32+
public LocalEntry(String name, TypeEntry type, int slot, int line) {
33+
/*
34+
* Use a AtomicInteger for the line number as it might change if we encounter the same local
35+
* variable in a different frame state with a lower line number
36+
*/
37+
this(name, type, slot, new AtomicInteger(line));
38+
}
2939

3040
@Override
3141
public String toString() {
32-
return String.format("Local(%s type=%s slot=%d line=%d)", name, type.getTypeName(), slot, line);
42+
return String.format("Local(%s type=%s slot=%d line=%d)", name, type.getTypeName(), slot, getLine());
43+
}
44+
45+
public void setLine(int line) {
46+
this.line.set(line);
47+
}
48+
49+
public int getLine() {
50+
return line.get();
3351
}
3452
}

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/MemberEntry.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ public FileEntry getFileEntry() {
8181
return fileEntry;
8282
}
8383

84+
/**
85+
* Fetch the file index from its owner class entry with {@link ClassEntry#getFileIdx}. The file
86+
* entry must only be fetched for members whose owner is a {@link ClassEntry}.
87+
*
88+
* @return the file index of this members file in the owner class entry
89+
*/
8490
public int getFileIdx() {
8591
if (ownerType instanceof ClassEntry) {
8692
return ((ClassEntry) ownerType).getFileIdx(fileEntry);

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/MethodEntry.java

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,17 @@ public MethodEntry(FileEntry fileEntry, int line, String methodName, StructureTy
6161
this.lastParamSlot = lastParamSlot;
6262

6363
this.locals = new ConcurrentSkipListSet<>(Comparator.comparingInt(LocalEntry::slot).thenComparing(LocalEntry::name).thenComparing(le -> le.type().getTypeName()));
64-
// sort by line and add all locals, such that the methods locals only contain the lowest
65-
// line number
66-
locals.stream().sorted(Comparator.comparingInt(LocalEntry::line)).forEach(this.locals::add);
64+
/*
65+
* Sort by line and add all locals, such that the methods locals only contain the lowest
66+
* line number.
67+
*/
68+
locals.stream().sorted(Comparator.comparingInt(LocalEntry::getLine)).forEach(this.locals::add);
6769

70+
/*
71+
* Flags to identify compiled methods. We set inRange if there is a compilation for this
72+
* method and inlined if it is encountered as a CallNode when traversing the compilation
73+
* result frame tree.
74+
*/
6875
this.isInRange = false;
6976
this.isInlined = false;
7077
}
@@ -92,6 +99,24 @@ public LocalEntry getThisParam() {
9299
return thisParam;
93100
}
94101

102+
/**
103+
* Returns the local entry for a given name slot and type entry. Decides with the slot number
104+
* whether this is a parameter or local variable.
105+
*
106+
* <p>
107+
* Local variable might not be contained in this method entry. Creates a new local entry in
108+
* {@link #locals} with the given parameters.
109+
* <p>
110+
* For locals, we also make sure that the line information is the lowest line encountered in
111+
* local variable lookups. If a new lower line number is encountered for an existing local
112+
* entry, we update the line number in the local entry.
113+
*
114+
* @param name the given name
115+
* @param slot the given slot
116+
* @param type the given {@code TypeEntry}
117+
* @param line the given line
118+
* @return the local entry stored in {@link #locals}
119+
*/
95120
public LocalEntry lookupLocalEntry(String name, int slot, TypeEntry type, int line) {
96121
if (slot < 0) {
97122
return null;
@@ -115,12 +140,18 @@ public LocalEntry lookupLocalEntry(String name, int slot, TypeEntry type, int li
115140
* contained, we might update the line number to the lowest occurring line number.
116141
*/
117142
LocalEntry local = new LocalEntry(name, type, slot, line);
118-
if (!locals.contains(local) || locals.removeIf(le -> le.slot() == slot && le.name().equals(name) && le.type().equals(type) && le.line() > line)) {
119-
locals.add(local);
120-
return local;
121-
} else {
122-
return locals.headSet(local, true).last();
143+
if (!locals.add(local)) {
144+
/*
145+
* Fetch local from locals list. This iterates over all locals to create the head
146+
* set and then takes the last value.
147+
*/
148+
local = locals.headSet(local, true).last();
149+
// Update line number if a lower one was encountered.
150+
if (local.getLine() > line) {
151+
local.setLine(line);
152+
}
123153
}
154+
return local;
124155
}
125156

126157
/*

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/range/Range.java

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ public abstract class Range implements Comparable<Range> {
9797
* alternatively, marked as invalid in this range.
9898
*/
9999
private final Map<LocalEntry, LocalValueEntry> localValueInfos;
100+
/**
101+
* Mapping of local entries to subranges they occur in.
102+
*/
103+
private final Map<LocalEntry, List<Range>> varRangeMap = new HashMap<>();
100104

101105
/**
102106
* Create a primary range representing the root of the subrange tree for a top level compiled
@@ -153,19 +157,31 @@ protected Range(PrimaryRange primary, MethodEntry methodEntry, Map<LocalEntry, L
153157
this.localValueInfos = localValueInfos;
154158
}
155159

160+
/**
161+
* Splits an initial range at the given stack decrement point. The lower split will stay as it
162+
* with its high offset reduced to the stack decrement point. The higher split starts at the
163+
* stack decrement point and has updated local value entries for the parameters in the then
164+
* extended stack.
165+
*
166+
* @param stackDecrement the offset to split the range at
167+
* @param frameSize the frame size after the split
168+
* @param preExtendFrameSize the frame size before the split
169+
* @return the higher split, that has been split off the original {@code Range}
170+
*/
156171
public Range split(int stackDecrement, int frameSize, int preExtendFrameSize) {
157-
// this should be for an initial range extending beyond the stack decrement
172+
// This should be for an initial range extending beyond the stack decrement.
158173
assert loOffset == 0 && loOffset < stackDecrement && stackDecrement < hiOffset : "invalid split request";
159174

160175
Map<LocalEntry, LocalValueEntry> splitLocalValueInfos = new HashMap<>();
161176

162177
for (var localInfo : localValueInfos.entrySet()) {
163178
if (localInfo.getValue() instanceof StackValueEntry stackValue) {
164-
// need to redefine the value for this param using a stack slot value
165-
// that allows for the stack being extended by framesize. however we
166-
// also need to remove any adjustment that was made to allow for the
167-
// difference between the caller SP and the pre-extend callee SP
168-
// because of a stacked return address.
179+
/*
180+
* Need to redefine the value for this param using a stack slot value that allows
181+
* for the stack being extended by framesize. however we also need to remove any
182+
* adjustment that was made to allow for the difference between the caller SP and
183+
* the pre-extend callee SP because of a stacked return address.
184+
*/
169185
int adjustment = frameSize - preExtendFrameSize;
170186
splitLocalValueInfos.put(localInfo.getKey(), new StackValueEntry(stackValue.stackSlot() + adjustment));
171187
} else {
@@ -314,18 +330,34 @@ public int getDepth() {
314330
return depth;
315331
}
316332

333+
/**
334+
* Returns the subranges grouped by local entries in the subranges. If the map is empty, it
335+
* first tries to populate the map with its callees {@link #localValueInfos}.
336+
*
337+
* @return a mapping from local entries to subranges
338+
*/
317339
public Map<LocalEntry, List<Range>> getVarRangeMap() {
318-
HashMap<LocalEntry, List<Range>> varRangeMap = new HashMap<>();
319-
for (Range callee : getCallees()) {
320-
for (LocalEntry local : callee.localValueInfos.keySet()) {
321-
varRangeMap.computeIfAbsent(local, l -> new ArrayList<>()).add(callee);
340+
if (varRangeMap.isEmpty()) {
341+
for (Range callee : getCallees()) {
342+
for (LocalEntry local : callee.localValueInfos.keySet()) {
343+
varRangeMap.computeIfAbsent(local, l -> new ArrayList<>()).add(callee);
344+
}
322345
}
323346
}
347+
324348
return varRangeMap;
325349
}
326350

351+
/**
352+
* Returns whether subranges contain a value in {@link #localValueInfos} for a given local
353+
* entry. A value is valid if it exists, and it can be represented as local values in the debug
354+
* info.
355+
*
356+
* @param local the local entry to check for
357+
* @return whether a local entry has a value in any of this range's subranges
358+
*/
327359
public boolean hasLocalValues(LocalEntry local) {
328-
for (Range callee : getCallees()) {
360+
for (Range callee : getVarRangeMap().getOrDefault(local, List.of())) {
329361
LocalValueEntry localValue = callee.lookupValue(local);
330362
if (localValue != null) {
331363
if (localValue instanceof ConstantValueEntry constantValueEntry) {

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debuginfo/DebugInfoProvider.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import java.util.SortedSet;
3030

3131
import com.oracle.objectfile.debugentry.CompiledMethodEntry;
32-
import com.oracle.objectfile.debugentry.StringTable;
3332
import com.oracle.objectfile.debugentry.TypeEntry;
3433

3534
/**
@@ -69,8 +68,6 @@ public interface DebugInfoProvider {
6968
*/
7069
int objectAlignment();
7170

72-
StringTable getStringTable();
73-
7471
SortedSet<TypeEntry> typeEntries();
7572

7673
SortedSet<CompiledMethodEntry> compiledMethodEntries();

0 commit comments

Comments
 (0)