(final Label label)
| 1198 | } |
| 1199 | |
| 1200 | @Override |
| 1201 | public void visitLabel(final Label label) { |
| 1202 | // Resolve the forward references to this label, if any. |
| 1203 | hasAsmInstructions |= label.resolve(code.data, code.length); |
| 1204 | // visitLabel starts a new basic block (except for debug only labels), so we need to update the |
| 1205 | // previous and current block references and list of successors. |
| 1206 | if ((label.flags & Label.FLAG_DEBUG_ONLY) != 0) { |
| 1207 | return; |
| 1208 | } |
| 1209 | if (compute == COMPUTE_ALL_FRAMES) { |
| 1210 | if (currentBasicBlock != null) { |
| 1211 | if (label.bytecodeOffset == currentBasicBlock.bytecodeOffset) { |
| 1212 | // We use {@link Label#getCanonicalInstance} to store the state of a basic block in only |
| 1213 | // one place, but this does not work for labels which have not been visited yet. |
| 1214 | // Therefore, when we detect here two labels having the same bytecode offset, we need to |
| 1215 | // - consolidate the state scattered in these two instances into the canonical instance: |
| 1216 | currentBasicBlock.flags |= (label.flags & Label.FLAG_JUMP_TARGET); |
| 1217 | // - make sure the two instances share the same Frame instance (the implementation of |
| 1218 | // {@link Label#getCanonicalInstance} relies on this property; here label.frame should be |
| 1219 | // null): |
| 1220 | label.frame = currentBasicBlock.frame; |
| 1221 | // - and make sure to NOT assign 'label' into 'currentBasicBlock' or 'lastBasicBlock', so |
| 1222 | // that they still refer to the canonical instance for this bytecode offset. |
| 1223 | return; |
| 1224 | } |
| 1225 | // End the current basic block (with one new successor). |
| 1226 | addSuccessorToCurrentBasicBlock(Edge.JUMP, label); |
| 1227 | } |
| 1228 | // Append 'label' at the end of the basic block list. |
| 1229 | if (lastBasicBlock != null) { |
| 1230 | if (label.bytecodeOffset == lastBasicBlock.bytecodeOffset) { |
| 1231 | // Same comment as above. |
| 1232 | lastBasicBlock.flags |= (label.flags & Label.FLAG_JUMP_TARGET); |
| 1233 | // Here label.frame should be null. |
| 1234 | label.frame = lastBasicBlock.frame; |
| 1235 | currentBasicBlock = lastBasicBlock; |
| 1236 | return; |
| 1237 | } |
| 1238 | lastBasicBlock.nextBasicBlock = label; |
| 1239 | } |
| 1240 | lastBasicBlock = label; |
| 1241 | // Make it the new current basic block. |
| 1242 | currentBasicBlock = label; |
| 1243 | // Here label.frame should be null. |
| 1244 | label.frame = new Frame(label); |
| 1245 | } else if (compute == COMPUTE_INSERTED_FRAMES) { |
| 1246 | if (currentBasicBlock == null) { |
| 1247 | // This case should happen only once, for the visitLabel call in the constructor. Indeed, if |
| 1248 | // compute is equal to COMPUTE_INSERTED_FRAMES, currentBasicBlock stays unchanged. |
| 1249 | currentBasicBlock = label; |
| 1250 | } else { |
| 1251 | // Update the frame owner so that a correct frame offset is computed in Frame.accept(). |
| 1252 | currentBasicBlock.frame.owner = label; |
| 1253 | } |
| 1254 | } else if (compute == COMPUTE_MAX_STACK_AND_LOCAL) { |
| 1255 | if (currentBasicBlock != null) { |
| 1256 | // End the current basic block (with one new successor). |
| 1257 | currentBasicBlock.outputStackMax = (short) maxRelativeStackSize; |
no test coverage detected