MCPcopy Index your code
hub / github.com/clojure/clojure / visitJumpInsn

Method visitJumpInsn

src/jvm/clojure/asm/MethodWriter.java:1094–1198  ·  view source on GitHub ↗
(final int opcode, final Label label)

Source from the content-addressed store, hash-verified

1092 }
1093
1094 @Override
1095 public void visitJumpInsn(final int opcode, final Label label) {
1096 lastBytecodeOffset = code.length;
1097 // Add the instruction to the bytecode of the method.
1098 // Compute the 'base' opcode, i.e. GOTO or JSR if opcode is GOTO_W or JSR_W, otherwise opcode.
1099 int baseOpcode =
1100 opcode >= Constants.GOTO_W ? opcode - Constants.WIDE_JUMP_OPCODE_DELTA : opcode;
1101 boolean nextInsnIsJumpTarget = false;
1102 if ((label.flags & Label.FLAG_RESOLVED) != 0
1103 && label.bytecodeOffset - code.length < Short.MIN_VALUE) {
1104 // Case of a backward jump with an offset < -32768. In this case we automatically replace GOTO
1105 // with GOTO_W, JSR with JSR_W and IFxxx <l> with IFNOTxxx <L> GOTO_W <l> L:..., where
1106 // IFNOTxxx is the "opposite" opcode of IFxxx (e.g. IFNE for IFEQ) and where <L> designates
1107 // the instruction just after the GOTO_W.
1108 if (baseOpcode == Opcodes.GOTO) {
1109 code.putByte(Constants.GOTO_W);
1110 } else if (baseOpcode == Opcodes.JSR) {
1111 code.putByte(Constants.JSR_W);
1112 } else {
1113 // Put the "opposite" opcode of baseOpcode. This can be done by flipping the least
1114 // significant bit for IFNULL and IFNONNULL, and similarly for IFEQ ... IF_ACMPEQ (with a
1115 // pre and post offset by 1). The jump offset is 8 bytes (3 for IFNOTxxx, 5 for GOTO_W).
1116 code.putByte(baseOpcode >= Opcodes.IFNULL ? baseOpcode ^ 1 : ((baseOpcode + 1) ^ 1) - 1);
1117 code.putShort(8);
1118 // Here we could put a GOTO_W in theory, but if ASM specific instructions are used in this
1119 // method or another one, and if the class has frames, we will need to insert a frame after
1120 // this GOTO_W during the additional ClassReader -> ClassWriter round trip to remove the ASM
1121 // specific instructions. To not miss this additional frame, we need to use an ASM_GOTO_W
1122 // here, which has the unfortunate effect of forcing this additional round trip (which in
1123 // some case would not have been really necessary, but we can't know this at this point).
1124 code.putByte(Constants.ASM_GOTO_W);
1125 hasAsmInstructions = true;
1126 // The instruction after the GOTO_W becomes the target of the IFNOT instruction.
1127 nextInsnIsJumpTarget = true;
1128 }
1129 label.put(code, code.length - 1, true);
1130 } else if (baseOpcode != opcode) {
1131 // Case of a GOTO_W or JSR_W specified by the user (normally ClassReader when used to remove
1132 // ASM specific instructions). In this case we keep the original instruction.
1133 code.putByte(opcode);
1134 label.put(code, code.length - 1, true);
1135 } else {
1136 // Case of a jump with an offset >= -32768, or of a jump with an unknown offset. In these
1137 // cases we store the offset in 2 bytes (which will be increased via a ClassReader ->
1138 // ClassWriter round trip if it turns out that 2 bytes are not sufficient).
1139 code.putByte(baseOpcode);
1140 label.put(code, code.length - 1, false);
1141 }
1142
1143 // If needed, update the maximum stack size and number of locals, and stack map frames.
1144 if (currentBasicBlock != null) {
1145 Label nextBasicBlock = null;
1146 if (compute == COMPUTE_ALL_FRAMES) {
1147 currentBasicBlock.frame.execute(baseOpcode, 0, null, null);
1148 // Record the fact that 'label' is the target of a jump instruction.
1149 label.getCanonicalInstance().flags |= Label.FLAG_JUMP_TARGET;
1150 // Add 'label' as a successor of the current basic block.
1151 addSuccessorToCurrentBasicBlock(Edge.JUMP, label);

Callers 11

doEmitMethod · 0.45
emitMethod · 0.45
emitProtoMethod · 0.45
emitThenForHashesMethod · 0.45
readCodeMethod · 0.45
ifCmpMethod · 0.45
ifZCmpMethod · 0.45
ifNullMethod · 0.45
ifNonNullMethod · 0.45
goToMethod · 0.45

Calls 8

visitLabelMethod · 0.95
putByteMethod · 0.80
putShortMethod · 0.80
getCanonicalInstanceMethod · 0.80
putMethod · 0.45
executeMethod · 0.45

Tested by

no test coverage detected