@@ -733,10 +733,11 @@ private MethodEntry createMethodEntry(SharedMethod method) {
733
733
boolean isOverride = isOverride (method );
734
734
boolean isDeopt = method .isDeoptTarget ();
735
735
boolean isConstructor = method .isConstructor ();
736
+ boolean isCompiledInPriorLayer = isCompiledInPriorLayer (method );
736
737
737
738
return new MethodEntry (fileEntry , line , methodName , ownerType ,
738
739
valueType , modifiers , params , symbolName , isDeopt , isOverride , isConstructor ,
739
- vTableOffset , lastParamSlot );
740
+ isCompiledInPriorLayer , vTableOffset , lastParamSlot );
740
741
}
741
742
742
743
/**
@@ -1010,6 +1011,10 @@ public boolean isOverride(@SuppressWarnings("unused") SharedMethod method) {
1010
1011
return false ;
1011
1012
}
1012
1013
1014
+ public boolean isCompiledInPriorLayer (@ SuppressWarnings ("unused" ) SharedMethod method ) {
1015
+ return false ;
1016
+ }
1017
+
1013
1018
public boolean isVirtual (@ SuppressWarnings ("unused" ) SharedMethod method ) {
1014
1019
return false ;
1015
1020
}
@@ -1217,7 +1222,7 @@ protected LocalEntry lookupLocalEntry(String name, TypeEntry typeEntry, int slot
1217
1222
/**
1218
1223
* Lookup a {@code LocalValueEntry}. This can either be a register, stack, constant value. This
1219
1224
* allows to reuse the same entries for multiple ranges.
1220
- *
1225
+ *
1221
1226
* @param localValueEntry the {@code LocalValueEntry} to lookup
1222
1227
* @return the {@code LocalValueEntry} from the lookup map
1223
1228
*/
@@ -1403,7 +1408,7 @@ private Map<LocalEntry, LocalValueEntry> initSyntheticInfoList(ParamLocationProd
1403
1408
debug .log (DebugContext .DETAILED_LEVEL , "local[%d] %s type %s slot %d" , paramIdx + 1 , param .name (), param .type ().getTypeName (), param .slot ());
1404
1409
debug .log (DebugContext .DETAILED_LEVEL , " => %s" , value );
1405
1410
}
1406
- LocalValueEntry localValueEntry = createLocalValueEntry (value , PRE_EXTEND_FRAME_SIZE );
1411
+ LocalValueEntry localValueEntry = createLocalValueEntry (value , PRE_EXTEND_FRAME_SIZE , true );
1407
1412
if (localValueEntry != null ) {
1408
1413
localValueInfos .put (param , localValueEntry );
1409
1414
}
@@ -1565,7 +1570,13 @@ public Range process(CompilationResultFrameTree.FrameNode node, CallRange caller
1565
1570
LineNumberTable lineNumberTable = method .getLineNumberTable ();
1566
1571
int line = lineNumberTable == null ? -1 : lineNumberTable .getLineNumber (pos .getBCI ());
1567
1572
1568
- Map <LocalEntry , LocalValueEntry > localValueInfos = initLocalInfoList (pos , methodEntry , frameSize );
1573
+ /*
1574
+ * Locals are stored in both leaf ranges and call ranges. However, for call ranges we do
1575
+ * not want to store register values as registers may be overwritten in callee ranges.
1576
+ * Thus, a debugger is still able to process stack values and constants for stack
1577
+ * traces.
1578
+ */
1579
+ Map <LocalEntry , LocalValueEntry > localValueInfos = initLocalInfoList (pos , methodEntry , frameSize , isLeaf );
1569
1580
Range locationInfo = Range .createSubrange (primary , methodEntry , localValueInfos , node .getStartPos (), node .getEndPos () + 1 , line , callerInfo , isLeaf );
1570
1581
1571
1582
if (debug .isLogEnabled ()) {
@@ -1585,9 +1596,10 @@ public Range process(CompilationResultFrameTree.FrameNode node, CallRange caller
1585
1596
* @param pos the bytecode position of the location info
1586
1597
* @param methodEntry the {@code MethodEntry} corresponding to the bytecode position
1587
1598
* @param frameSize the current frame size
1599
+ * @param isLeaf whether the range to create this value for is a leaf range
1588
1600
* @return a mapping from {@code LocalEntry} to {@code LocalValueEntry}
1589
1601
*/
1590
- protected Map <LocalEntry , LocalValueEntry > initLocalInfoList (BytecodePosition pos , MethodEntry methodEntry , int frameSize ) {
1602
+ protected Map <LocalEntry , LocalValueEntry > initLocalInfoList (BytecodePosition pos , MethodEntry methodEntry , int frameSize , boolean isLeaf ) {
1591
1603
Map <LocalEntry , LocalValueEntry > localInfos = new HashMap <>();
1592
1604
1593
1605
if (pos instanceof BytecodeFrame frame && frame .numLocals > 0 ) {
@@ -1688,7 +1700,7 @@ protected Map<LocalEntry, LocalValueEntry> initLocalInfoList(BytecodePosition po
1688
1700
* upfront from the local variable table, the LocalEntry already exists.
1689
1701
*/
1690
1702
LocalEntry localEntry = methodEntry .getOrAddLocalEntry (lookupLocalEntry (name , typeEntry , slot ), line );
1691
- LocalValueEntry localValueEntry = createLocalValueEntry (value , frameSize );
1703
+ LocalValueEntry localValueEntry = createLocalValueEntry (value , frameSize , isLeaf );
1692
1704
if (localEntry != null && localValueEntry != null ) {
1693
1705
localInfos .put (localEntry , localValueEntry );
1694
1706
}
@@ -1703,16 +1715,24 @@ protected Map<LocalEntry, LocalValueEntry> initLocalInfoList(BytecodePosition po
1703
1715
1704
1716
/**
1705
1717
* Creates a {@code LocalValueEntry} for a given {@code JavaValue}. This processes register
1706
- * values, stack values, primitive constants and constant in the heap.
1718
+ * values, stack values, primitive constants and constant in the heap. Register values are only
1719
+ * added for leaf frames, as register may be overwritten within callee frames of a call range.
1720
+ * But, stack values and constants also work for call ranges.
1707
1721
*
1708
1722
* @param value the given {@code JavaValue}
1709
1723
* @param frameSize the frame size for stack values
1724
+ * @param isLeaf whether the range to create this value for is a leaf range
1710
1725
* @return the {@code LocalValueEntry} or {@code null} if the value can't be processed
1711
1726
*/
1712
- private LocalValueEntry createLocalValueEntry (JavaValue value , int frameSize ) {
1727
+ private LocalValueEntry createLocalValueEntry (JavaValue value , int frameSize , boolean isLeaf ) {
1713
1728
switch (value ) {
1714
1729
case RegisterValue registerValue -> {
1715
- return lookupLocalValueEntry (new RegisterValueEntry (registerValue .getRegister ().number ));
1730
+ /*
1731
+ * We only want to create register entries for leaf nodes. Thus, they are only valid
1732
+ * within a leaf range but not over a whole call range where the register value is
1733
+ * potentially overwritten.
1734
+ */
1735
+ return isLeaf ? lookupLocalValueEntry (new RegisterValueEntry (registerValue .getRegister ().number )) : null ;
1716
1736
}
1717
1737
case StackSlot stackValue -> {
1718
1738
int stackSlot = frameSize == 0 ? stackValue .getRawOffset () : stackValue .getOffset (frameSize );
@@ -1827,7 +1847,7 @@ private Range createEmbeddedParentLocationInfo(PrimaryRange primary, Compilation
1827
1847
LineNumberTable lineNumberTable = method .getLineNumberTable ();
1828
1848
int line = lineNumberTable == null ? -1 : lineNumberTable .getLineNumber (pos .getBCI ());
1829
1849
1830
- Map <LocalEntry , LocalValueEntry > localValueInfos = initLocalInfoList (pos , methodEntry , frameSize );
1850
+ Map <LocalEntry , LocalValueEntry > localValueInfos = initLocalInfoList (pos , methodEntry , frameSize , true );
1831
1851
Range locationInfo = Range .createSubrange (primary , methodEntry , localValueInfos , startPos , endPos , line , callerLocation , true );
1832
1852
1833
1853
if (debug .isLogEnabled ()) {
@@ -1881,7 +1901,7 @@ private static boolean skipPos(BytecodePosition pos) {
1881
1901
* at native image build-time while still having comparable performance (for most of the index
1882
1902
* maps). The most performance critical maps that see more traffic will use the less memory
1883
1903
* efficient ConcurrentHashMaps instead.
1884
- *
1904
+ *
1885
1905
* @param map the {@code EconomicMap} to perform {@code computeIfAbsent} on
1886
1906
* @param key the key to look for
1887
1907
* @param mappingFunction the function producing the value for a given key
0 commit comments