@@ -768,12 +768,20 @@ private CodeExecutableElement createContinueAt() {
768768 b.lineComment("Bytecode or tier changed");
769769 b.tree(GeneratorUtils.createTransferToInterpreterAndInvalidate());
770770
771- if (model.isBytecodeUpdatable()) {
771+ if (model.isBytecodeUpdatable() || model.hasYieldOperation() ) {
772772 b.declaration(abstractBytecodeNode.asType(), "oldBytecode", "bc");
773773 b.statement("bc = this.bytecode");
774- b.startAssign("state").startCall("oldBytecode.transitionState");
774+
775+ if (model.isBytecodeUpdatable()) {
776+ b.startAssign("state");
777+ } else {
778+ b.startStatement();
779+ }
780+ b.startCall("oldBytecode.transition");
775781 b.string("bc");
776- b.string("state");
782+ if (model.isBytecodeUpdatable()) {
783+ b.string("state");
784+ }
777785 if (model.hasYieldOperation()) {
778786 b.string("continuationRootNode");
779787 }
@@ -11772,8 +11780,10 @@ final class AbstractBytecodeNodeElement extends CodeTypeElement {
1177211780 }
1177311781
1177411782 this.add(createTranslateBytecodeIndex());
11783+ if (model.isBytecodeUpdatable() || model.hasYieldOperation()) {
11784+ this.add(createTransition());
11785+ }
1177511786 if (model.isBytecodeUpdatable()) {
11776- this.add(createTransitionState());
1177711787 this.add(createToStableBytecodeIndex());
1177811788 this.add(createFromStableBytecodeIndex());
1177911789 this.add(createTransitionInstrumentationIndex());
@@ -12612,7 +12622,7 @@ private CodeExecutableElement createTranslateBytecodeIndex() {
1261212622 if (model.isBytecodeUpdatable()) {
1261312623
1261412624 CodeTreeBuilder tb = CodeTreeBuilder.createBuilder();
12615- tb.startCall("transitionState ");
12625+ tb.startCall("transition ");
1261612626 tb.startGroup();
1261712627 tb.cast(this.asType());
1261812628 tb.string("newNode");
@@ -12632,18 +12642,20 @@ private CodeExecutableElement createTranslateBytecodeIndex() {
1263212642 return ex;
1263312643 }
1263412644
12635- private CodeExecutableElement createTransitionState() {
12636- CodeExecutableElement transitionState = new CodeExecutableElement(Set.of(FINAL), type(long.class), "transitionState");
12637- transitionState.addParameter(new CodeVariableElement(this.asType(), "newBytecode"));
12638- transitionState.addParameter(new CodeVariableElement(type(long.class), "state"));
12645+ private CodeExecutableElement createTransition() {
12646+ // Returns updated state long, if updatable.
12647+ TypeMirror returnType = model.isBytecodeUpdatable() ? type(long.class) : type(void.class);
12648+
12649+ CodeExecutableElement ex = new CodeExecutableElement(Set.of(FINAL), returnType, "transition");
12650+ ex.addParameter(new CodeVariableElement(this.asType(), "newBytecode"));
12651+ if (model.isBytecodeUpdatable()) {
12652+ ex.addParameter(new CodeVariableElement(type(long.class), "state"));
12653+ }
1263912654 if (model.hasYieldOperation()) {
12640- transitionState .addParameter(new CodeVariableElement(continuationRootNodeImpl.asType(), "continuationRootNode"));
12655+ ex .addParameter(new CodeVariableElement(continuationRootNodeImpl.asType(), "continuationRootNode"));
1264112656 }
1264212657
12643- CodeTreeBuilder b = transitionState.createBuilder();
12644-
12645- b.declaration(arrayOf(type(byte.class)), "oldBc", "this.oldBytecodes");
12646- b.declaration(arrayOf(type(byte.class)), "newBc", "newBytecode.bytecodes");
12658+ CodeTreeBuilder b = ex.createBuilder();
1264712659
1264812660 if (model.hasYieldOperation()) {
1264912661 /*
@@ -12657,7 +12669,7 @@ private CodeExecutableElement createTransitionState() {
1265712669 * patches all ContinuationRootNodes with the new bytecode, we don't have to update
1265812670 * anything.
1265912671 */
12660- b.startIf().string("continuationRootNode != null && oldBc == null ").end().startBlock();
12672+ b.startIf().string("continuationRootNode != null && this.getTier() == ").staticReference(types.BytecodeTier, "UNCACHED ").end().startBlock();
1266112673 b.lineComment("Transition continuationRootNode to cached.");
1266212674
1266312675 b.startDeclaration(types.BytecodeLocation, "newContinuationLocation");
@@ -12675,34 +12687,38 @@ private CodeExecutableElement createTransitionState() {
1267512687 b.end();
1267612688 }
1267712689
12678- b.startIf().string("oldBc == null || this == newBytecode || this.bytecodes == newBc").end().startBlock();
12679- b.lineComment("No change in bytecodes.");
12680- b.startReturn().string("state").end();
12681- b.end();
12690+ if (model.isBytecodeUpdatable()) {
12691+ b.declaration(arrayOf(type(byte.class)), "oldBc", "this.oldBytecodes");
12692+ b.declaration(arrayOf(type(byte.class)), "newBc", "newBytecode.bytecodes");
12693+ b.startIf().string("oldBc == null || this == newBytecode || this.bytecodes == newBc").end().startBlock();
12694+ b.lineComment("No change in bytecodes.");
12695+ b.startReturn().string("state").end();
12696+ b.end();
1268212697
12683- b.declaration(type(int.class), "oldBci", decodeBci("state"));
12698+ b.declaration(type(int.class), "oldBci", decodeBci("state"));
1268412699
12685- b.startDeclaration(type(int.class), "newBci");
12686- b.startCall("computeNewBci").string("oldBci").string("oldBc").string("newBc");
12687- if (model.enableTagInstrumentation) {
12688- b.string("this.getTagNodes()");
12689- b.string("newBytecode.getTagNodes()");
12690- }
12691- b.end(); // call
12700+ b.startDeclaration(type(int.class), "newBci");
12701+ b.startCall("computeNewBci").string("oldBci").string("oldBc").string("newBc");
12702+ if (model.enableTagInstrumentation) {
12703+ b.string("this.getTagNodes()");
12704+ b.string("newBytecode.getTagNodes()");
12705+ }
12706+ b.end(); // call
1269212707
12693- b.end();
12708+ b.end();
1269412709
12695- if (model.overridesBytecodeDebugListenerMethod("onBytecodeStackTransition")) {
12696- b.startStatement();
12697- b.startCall("getRoot().onBytecodeStackTransition");
12698- emitParseInstruction(b, "this", "oldBci", readInstruction("oldBc", "oldBci"));
12699- emitParseInstruction(b, "newBytecode", "newBci", readInstruction("newBc", "newBci"));
12700- b.end().end();
12701- }
12710+ if (model.overridesBytecodeDebugListenerMethod("onBytecodeStackTransition")) {
12711+ b.startStatement();
12712+ b.startCall("getRoot().onBytecodeStackTransition");
12713+ emitParseInstruction(b, "this", "oldBci", readInstruction("oldBc", "oldBci"));
12714+ emitParseInstruction(b, "newBytecode", "newBci", readInstruction("newBc", "newBci"));
12715+ b.end().end();
12716+ }
1270212717
12703- b.startReturn().string(encodeNewBci("newBci", "state")).end();
12718+ b.startReturn().string(encodeNewBci("newBci", "state")).end();
12719+ }
1270412720
12705- return transitionState ;
12721+ return ex ;
1270612722 }
1270712723
1270812724 private CodeExecutableElement createTransitionInstrumentationIndex() {
@@ -12740,19 +12756,21 @@ public int compareTo(InstructionGroup o) {
1274012756 }
1274112757 }
1274212758
12743- CodeExecutableElement invalidate = new CodeExecutableElement(Set.of(PRIVATE, STATIC), type(int.class), "transitionInstrumentationIndex");
12744- invalidate .addParameter(new CodeVariableElement(arrayOf(type(byte.class)), "oldBc"));
12745- invalidate .addParameter(new CodeVariableElement(type(int.class), "oldBciBase"));
12746- invalidate .addParameter(new CodeVariableElement(type(int.class), "oldBciTarget"));
12747- invalidate .addParameter(new CodeVariableElement(arrayOf(type(byte.class)), "newBc"));
12748- invalidate .addParameter(new CodeVariableElement(type(int.class), "newBciBase"));
12759+ CodeExecutableElement ex = new CodeExecutableElement(Set.of(PRIVATE, STATIC), type(int.class), "transitionInstrumentationIndex");
12760+ ex .addParameter(new CodeVariableElement(arrayOf(type(byte.class)), "oldBc"));
12761+ ex .addParameter(new CodeVariableElement(type(int.class), "oldBciBase"));
12762+ ex .addParameter(new CodeVariableElement(type(int.class), "oldBciTarget"));
12763+ ex .addParameter(new CodeVariableElement(arrayOf(type(byte.class)), "newBc"));
12764+ ex .addParameter(new CodeVariableElement(type(int.class), "newBciBase"));
1274912765 if (model.enableTagInstrumentation) {
12750- invalidate .addParameter(new CodeVariableElement(arrayOf(tagNode.asType()), "oldTagNodes"));
12751- invalidate .addParameter(new CodeVariableElement(arrayOf(tagNode.asType()), "newTagNodes"));
12766+ ex .addParameter(new CodeVariableElement(arrayOf(tagNode.asType()), "oldTagNodes"));
12767+ ex .addParameter(new CodeVariableElement(arrayOf(tagNode.asType()), "newTagNodes"));
1275212768 }
12753- CodeTreeBuilder b = invalidate .createBuilder();
12769+ CodeTreeBuilder b = ex .createBuilder();
1275412770 b.declaration(type(int.class), "oldBci", "oldBciBase");
1275512771 b.declaration(type(int.class), "newBci", "newBciBase");
12772+ b.lineComment("Find the last instrumentation instruction executed before oldBciTarget.");
12773+ b.lineComment("The new bci should point directly after this reference instruction in the new bytecode.");
1275612774 b.declaration(type(short.class), "searchOp", "-1");
1275712775 if (model.enableTagInstrumentation) {
1275812776 b.declaration(type(int.class), "searchTags", "-1");
@@ -12765,7 +12783,7 @@ public int compareTo(InstructionGroup o) {
1276512783 for (var groupEntry : groupInstructionsSortedBy(InstructionGroup::new)) {
1276612784 InstructionGroup group = groupEntry.getKey();
1276712785 if (!group.instrumentation) {
12768- // seeing an instrumentation here is a failure
12786+ // only instrumentation instructions should be reached
1276912787 continue;
1277012788 }
1277112789 List<InstructionModel> instructions = groupEntry.getValue();
@@ -12795,7 +12813,8 @@ public int compareTo(InstructionGroup o) {
1279512813 b.end(); // while block
1279612814
1279712815 b.startAssert().string("searchOp != -1").end();
12798-
12816+ b.lineComment("The instruction may occur multiple times between oldBci and oldTargetBci.");
12817+ b.lineComment("Count the number of occurrences so that we identify the correct reference instruction.");
1279912818 b.startAssign("oldBci").string("oldBciBase").end();
1280012819 b.declaration(type(int.class), "opCounter", "0");
1280112820
@@ -12805,7 +12824,7 @@ public int compareTo(InstructionGroup o) {
1280512824 for (var groupEntry : groupInstructionsSortedBy(InstructionGroup::new)) {
1280612825 InstructionGroup group = groupEntry.getKey();
1280712826 if (!group.instrumentation) {
12808- // seeing an instrumentation here is a failure
12827+ // only instrumentation instructions should be reached
1280912828 continue;
1281012829 }
1281112830 List<InstructionModel> instructions = groupEntry.getValue();
@@ -12839,14 +12858,14 @@ public int compareTo(InstructionGroup o) {
1283912858 b.end(); // while block
1284012859
1284112860 b.startAssert().string("opCounter > 0").end();
12842-
12861+ b.lineComment("Walk the new bytecode to find the location directly after the reference instruction.");
1284312862 b.startWhile().string("opCounter > 0").end().startBlock();
1284412863 b.declaration(type(short.class), "op", readInstruction("newBc", "newBci"));
1284512864 b.startSwitch().string("op").end().startBlock();
1284612865 for (var groupEntry : groupInstructionsSortedBy(InstructionGroup::new)) {
1284712866 InstructionGroup group = groupEntry.getKey();
1284812867 if (!group.instrumentation) {
12849- // seeing an instrumentation here is a failure
12868+ // only instrumentation instructions should be reached
1285012869 continue;
1285112870 }
1285212871 List<InstructionModel> instructions = groupEntry.getValue();
@@ -12881,7 +12900,7 @@ public int compareTo(InstructionGroup o) {
1288112900
1288212901 b.startReturn().string("newBci").end();
1288312902
12884- return invalidate ;
12903+ return ex ;
1288512904 }
1288612905
1288712906 private CodeExecutableElement createComputeNewBci() {
0 commit comments