@@ -9665,8 +9665,7 @@ private CodeExecutableElement createValidateBytecodes() {
96659665 for (InstructionModel instr : model.getInstructions()) {
96669666 b.startCase().tree(createInstructionConstant(instr)).end().startBlock();
96679667
9668- // instruction data array
9669-
9668+ boolean rootNodeAvailable = false;
96709669 for (InstructionImmediate immediate : instr.getImmediates()) {
96719670 // argument data array
96729671 String readImmediate = "bc[bci + " + immediate.offset() + "]";
@@ -9696,26 +9695,27 @@ private CodeExecutableElement createValidateBytecodes() {
96969695 b.end();
96979696 break;
96989697 case LOCAL_OFFSET: {
9699- InstructionImmediate root = instr.getImmediate(ImmediateKind.LOCAL_ROOT);
9700- if (root == null) {
9701- b.startAssign("root").string("this.getRoot()").end();
9702- } else {
9703- b.startAssign("root").string("this.getRoot().getBytecodeRootNodeImpl(", readBc("bci + " + root.offset()), ")").end();
9698+ if (!rootNodeAvailable) {
9699+ rootNodeAvailable = tryEmitRootNodeForLocalInstruction(b, instr);
9700+ }
9701+ b.startIf().string(localName).string(" < USER_LOCALS_START_IDX");
9702+ if (rootNodeAvailable) {
9703+ b.string(" || ").string(localName).string(" >= root.maxLocals");
97049704 }
9705- b.startIf().string(localName).string(" - USER_LOCALS_START_IDX").string(" < 0 || ").string(localName).string(" - USER_LOCALS_START_IDX").string(
9706- " >= root.maxLocals").end().startBlock();
9705+ b.end().startBlock();
97079706 b.tree(createValidationErrorWithBci("local offset is out of bounds"));
97089707 b.end();
97099708 break;
97109709 }
97119710 case LOCAL_INDEX: {
9712- InstructionImmediate root = instr.getImmediate(ImmediateKind.LOCAL_ROOT);
9713- if (root == null) {
9714- b.startAssign("root").string("this.getRoot()").end();
9715- } else {
9716- b.startAssign("root").string("this.getRoot().getBytecodeRootNodeImpl(", readBc("bci + " + root.offset()), ")").end();
9711+ if (!rootNodeAvailable) {
9712+ rootNodeAvailable = tryEmitRootNodeForLocalInstruction(b, instr);
9713+ }
9714+ b.startIf().string(localName).string(" < 0");
9715+ if (rootNodeAvailable) {
9716+ b.string(" || ").string(localName).string(" >= root.numLocals");
97179717 }
9718- b.startIf().string(localName).string(" < 0 || ").string(localName).string(" >= root.numLocals"). end().startBlock();
9718+ b.end().startBlock();
97199719 b.tree(createValidationErrorWithBci("local index is out of bounds"));
97209720 b.end();
97219721 break;
@@ -9868,6 +9868,26 @@ private CodeExecutableElement createValidateBytecodes() {
98689868 return validate;
98699869 }
98709870
9871+ private boolean tryEmitRootNodeForLocalInstruction(CodeTreeBuilder b, InstructionModel instr) {
9872+ switch (instr.kind) {
9873+ case LOAD_LOCAL, STORE_LOCAL, CLEAR_LOCAL: {
9874+ b.startAssign("root").string("this.getRoot()").end();
9875+ return true;
9876+ }
9877+ case LOAD_LOCAL_MATERIALIZED, STORE_LOCAL_MATERIALIZED: {
9878+ InstructionImmediate rootImmediate = instr.getImmediate(ImmediateKind.LOCAL_ROOT);
9879+ if (rootImmediate != null) {
9880+ b.startAssign("root").startCall("this.getRoot().getBytecodeRootNodeImpl").tree(readImmediate("bc", "bci", rootImmediate)).end(2);
9881+ return true;
9882+ }
9883+ break;
9884+ }
9885+ default:
9886+ throw new AssertionError("Unexpected instruction: " + instr);
9887+ }
9888+ return false;
9889+ }
9890+
98719891 /**
98729892 * Returns true if the instruction can take -1 as a child bci.
98739893 */
0 commit comments