Skip to content

Commit b75c602

Browse files
committed
[GR-70581] Duplicate CodeMark upon assembly replay.
PullRequest: graal/22313
2 parents 69ba878 + ea40269 commit b75c602

File tree

7 files changed

+81
-22
lines changed

7 files changed

+81
-22
lines changed

compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/ThreadedInterpreterTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ private int countPotentialJumpTableJumps(byte[] code) {
409409
} else {
410410
if (opcodeJmpReg) {
411411
// preceding byte is 0xFF
412-
if ((b & 0xC2) == 0xC2) {
412+
if ((b & 0xF8) == 0xE0) {
413413
count++;
414414
}
415415
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/Assembler.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ public void stopRecordingCodeSnippet(CompilationResultBuilder crb) {
370370
if (recordedCodeSnippets == null) {
371371
recordedCodeSnippets = EconomicMap.create();
372372
}
373-
recordedCodeSnippets.put(currentCodeSnippet.codeStart, currentCodeSnippet);
373+
recordedCodeSnippets.put(currentCodeSnippet.getCodeStart(), currentCodeSnippet);
374374
currentCodeSnippet = null;
375375
}
376376
}
@@ -393,11 +393,11 @@ public boolean replayCodeSnippetAt(CompilationResultBuilder crb, int pos) {
393393
return false;
394394
}
395395

396-
protected boolean isRecordingCodeSnippet() {
396+
public boolean isRecordingCodeSnippet() {
397397
return currentCodeSnippet != null && currentCodeSnippet.isRecording();
398398
}
399399

400-
protected void abortRecordingCodeSnippet() {
400+
public void abortRecordingCodeSnippet() {
401401
currentCodeSnippet = null;
402402
}
403403

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/CodeSnippetRecord.java

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,31 +24,42 @@
2424
*/
2525
package jdk.graal.compiler.asm;
2626

27-
import jdk.vm.ci.code.site.ImplicitExceptionDispatch;
28-
import jdk.vm.ci.code.site.Site;
2927
import org.graalvm.collections.EconomicMap;
3028

3129
import jdk.graal.compiler.code.CompilationResult.CompilationResultWatermark;
30+
import jdk.graal.compiler.lir.LIR;
3231
import jdk.graal.compiler.lir.asm.CompilationResultBuilder;
32+
import jdk.vm.ci.code.site.ImplicitExceptionDispatch;
33+
import jdk.vm.ci.code.site.Site;
3334

3435
/**
3536
* Records a snippet of emitted assembly. The recorded snippet can be replayed, i.e., inserted into
3637
* the code buffer at different positions, multiple times. On each replay, the snippet is patched
3738
* based on its insertion position.
39+
*
40+
* If a slow path is added via {@link LIR#addSlowPath} during recording, it will not be duplicated
41+
* during replay, as the replay only copies the exact bytes between {@link #codeStart} and
42+
* {@link #codeEnd}. As a result, all replayed snippets will jump to the same slow path. The slow
43+
* path may jump back to the originally recorded snippet (e.g., in the G1 write barrier, or ZGC load
44+
* and write barriers). This behavior is semantically correct because each replayed snippet is a
45+
* complete replica. However, it may reduce the effectiveness of branch prediction optimizations
46+
* introduced by the assembly replay mechanism. To preserve potential branch predictor benefits,
47+
* {@link LIR#addSlowPath} should be reserved exclusively for genuine slow paths that are
48+
* infrequently taken and do not usually jump back to the original snippet.
3849
*/
39-
final class CodeSnippetRecord {
40-
int codeStart;
41-
int codeEnd;
42-
EconomicMap<Integer, Label> codePatchLabels;
50+
public final class CodeSnippetRecord {
51+
private int codeStart;
52+
private int codeEnd;
53+
private EconomicMap<Integer, Label> codePatchLabels;
4354

4455
/**
4556
* Watermarks represent the sizes of recorded or pending {@link Site}s essential for execution,
4657
* e.g., {@link ImplicitExceptionDispatch}. By capturing watermarks at the start and end of code
4758
* execution, we can identify the {@link Site}s appended during recording and replicate them
4859
* during replay.
4960
*/
50-
CompilationResultWatermark watermarkAtCodeStart;
51-
CompilationResultWatermark watermarkAtCodeEnd;
61+
private CompilationResultWatermark watermarkAtCodeStart;
62+
private CompilationResultWatermark watermarkAtCodeEnd;
5263

5364
CodeSnippetRecord(int codeStart, CompilationResultWatermark watermark) {
5465
this.codeStart = codeStart;
@@ -58,6 +69,10 @@ final class CodeSnippetRecord {
5869
this.codePatchLabels = EconomicMap.create();
5970
}
6071

72+
int getCodeStart() {
73+
return codeStart;
74+
}
75+
6176
boolean isRecording() {
6277
return codeStart != -1 && codeEnd == -1;
6378
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/code/CompilationResult.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,13 @@ public interface MarkId {
726726
default Object getId() {
727727
return this;
728728
}
729+
730+
/**
731+
* @return {@code true} if only one instance of this {@code MarkID} is allowed
732+
*/
733+
default boolean isUnique() {
734+
return true;
735+
}
729736
}
730737

731738
/**
@@ -883,6 +890,7 @@ public static String getSignature(byte[] data) {
883890
public record CompilationResultWatermark(int infopointsSize,
884891
int dataPatchesSize,
885892
int exceptionHandlersSize,
893+
int marksSize,
886894
int pendingExceptionInfoListSize,
887895
int pendingImplicitExceptionListSize) {
888896
}
@@ -893,7 +901,7 @@ public record CompilationResultWatermark(int infopointsSize,
893901
* {@link ExceptionHandler} or {@link ImplicitExceptionDispatch}.
894902
*/
895903
public CompilationResultWatermark getSitesWatermark(int pendingExceptionInfoListSize, int pendingImplicitExceptionListSize) {
896-
return new CompilationResultWatermark(infopoints.size(), dataPatches.size(), exceptionHandlers.size(), pendingExceptionInfoListSize,
904+
return new CompilationResultWatermark(infopoints.size(), dataPatches.size(), exceptionHandlers.size(), marks.size(), pendingExceptionInfoListSize,
897905
pendingImplicitExceptionListSize);
898906
}
899907

@@ -925,6 +933,14 @@ private boolean verifySites(int codeStart, CompilationResultWatermark watermarkA
925933
assert codeOffset < codeStart || codeOffset >= codeEnd : Assertions.errorMessage(codeOffset, codeStart, codeEnd, exceptionHandlers);
926934
}
927935
}
936+
for (int i = 0; i < marks.size(); i++) {
937+
int codeOffset = marks.get(i).pcOffset;
938+
if (watermarkAtCodeStart.marksSize() <= i && i < watermarkAtCodeEnd.marksSize()) {
939+
assert codeStart <= codeOffset && codeOffset < codeEnd : Assertions.errorMessage(codeOffset, codeStart, codeEnd, marks);
940+
} else {
941+
assert codeOffset < codeStart || codeOffset >= codeEnd : Assertions.errorMessage(codeOffset, codeStart, codeEnd, marks);
942+
}
943+
}
928944
return true;
929945
}
930946

@@ -952,5 +968,9 @@ public void duplicateSites(int codeStart, CompilationResultWatermark watermarkAt
952968
ExceptionHandler handler = exceptionHandlers.get(i);
953969
exceptionHandlers.add(new ExceptionHandler(handler.pcOffset + offset, handler.handlerPos));
954970
}
971+
for (int i = watermarkAtCodeStart.marksSize; i < watermarkAtCodeEnd.marksSize; i++) {
972+
CodeMark mark = marks.get(i);
973+
marks.add(new CodeMark(mark.pcOffset + offset, mark.id));
974+
}
955975
}
956976
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotMarkId.java

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@
3333
* code.
3434
*/
3535
public enum HotSpotMarkId implements CompilationResult.MarkId {
36-
VERIFIED_ENTRY,
37-
UNVERIFIED_ENTRY,
38-
OSR_ENTRY,
39-
EXCEPTION_HANDLER_ENTRY,
40-
DEOPT_HANDLER_ENTRY,
41-
DEOPT_MH_HANDLER_ENTRY,
42-
FRAME_COMPLETE,
43-
ENTRY_BARRIER_PATCH,
36+
VERIFIED_ENTRY(true),
37+
UNVERIFIED_ENTRY(true),
38+
OSR_ENTRY(true),
39+
EXCEPTION_HANDLER_ENTRY(true),
40+
DEOPT_HANDLER_ENTRY(true),
41+
DEOPT_MH_HANDLER_ENTRY(true),
42+
FRAME_COMPLETE(true),
43+
ENTRY_BARRIER_PATCH(true),
4444
INVOKEINTERFACE,
4545
INVOKEVIRTUAL,
4646
INVOKESTATIC,
@@ -73,14 +73,24 @@ public enum HotSpotMarkId implements CompilationResult.MarkId {
7373

7474
private Integer value;
7575
private final String arch;
76+
private final boolean isUnique;
7677

7778
HotSpotMarkId() {
78-
this(null);
79+
this(null, false);
80+
}
81+
82+
HotSpotMarkId(boolean isUnique) {
83+
this(null, isUnique);
7984
}
8085

8186
HotSpotMarkId(String arch) {
87+
this(arch, false);
88+
}
89+
90+
HotSpotMarkId(String arch, boolean isUnique) {
8291
this.value = null;
8392
this.arch = arch;
93+
this.isUnique = isUnique;
8494
}
8595

8696
void setValue(Integer value) {
@@ -110,6 +120,11 @@ public boolean isAvailable() {
110120
return value != null;
111121
}
112122

123+
@Override
124+
public boolean isUnique() {
125+
return isUnique;
126+
}
127+
113128
@Override
114129
public String toString() {
115130
return "HotSpotCodeMark{" + name() +

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/LIR.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.ArrayList;
2828
import java.util.List;
2929

30+
import jdk.graal.compiler.asm.CodeSnippetRecord;
3031
import jdk.graal.compiler.asm.Label;
3132
import jdk.graal.compiler.core.common.cfg.AbstractControlFlowGraph;
3233
import jdk.graal.compiler.core.common.cfg.BasicBlock;
@@ -206,6 +207,10 @@ public ArrayList<LIRInstruction.LIRInstructionSlowPath> getSlowPaths() {
206207

207208
/**
208209
* Add a chunk of assembly that will be emitted out of line after all LIR has been emitted.
210+
*
211+
* If called during assembler code snippet recording, the slow path will not be duplicated.
212+
* Instead, it will be shared among replayed code snippets. See {@link CodeSnippetRecord} for
213+
* more details.
209214
*/
210215
public void addSlowPath(LIRInstruction op, Runnable slowPath) {
211216
if (slowPaths == null) {

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/asm/CompilationResultBuilder.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,10 @@ public void setMinDataSectionItemAlignment(int alignment) {
215215
* @return the recorded entry for the mark
216216
*/
217217
public CompilationResult.CodeMark recordMark(int codePos, CompilationResult.MarkId markId) {
218+
if (markId.isUnique() && asm.isRecordingCodeSnippet()) {
219+
// We cannot duplicate unique MarkId
220+
asm.abortRecordingCodeSnippet();
221+
}
218222
return compilationResult.recordMark(codePos, markId);
219223
}
220224

0 commit comments

Comments
 (0)