372 System.arraycopy(srcAndRefPositions, 0, a, 0,
373 srcAndRefPositions.length);
374 srcAndRefPositions = a;
375 }
376 srcAndRefPositions[referenceCount++] = sourcePosition;
377 srcAndRefPositions[referenceCount++] = referencePosition;
378 }
379
380 /**
381 * Resolves all forward references to this label. This method must be called
382 * when this label is added to the bytecode of the method, i.e. when its
383 * position becomes known. This method fills in the blanks that where left
384 * in the bytecode by each forward reference previously added to this label.
385 *
386 * @param owner
387 * the code writer that calls this method.
388 * @param position
389 * the position of this label in the bytecode.
390 * @param data
391 * the bytecode of the method.
392 * @return <tt>true</tt> if a blank that was left for this label was to
393 * small to store the offset. In such a case the corresponding jump
394 * instruction is replaced with a pseudo instruction (using unused
395 * opcodes) using an unsigned two bytes offset. These pseudo
396 * instructions will need to be replaced with true instructions with
397 * wider offsets (4 bytes instead of 2). This is done in
398 * {@link MethodWriter#resizeInstructions}.
399 * @throws IllegalArgumentException
400 * if this label has already been resolved, or if it has not
401 * been created by the given code writer.
402 */
403 boolean resolve(final MethodWriter owner, final int position,
404 final byte[] data) {
405 boolean needUpdate = false;
406 this.status |= RESOLVED;
407 this.position = position;
408 int i = 0;
409 while (i < referenceCount) {
410 int source = srcAndRefPositions[i++];
411 int reference = srcAndRefPositions[i++];
412 int offset;
413 if (source >= 0) {
414 offset = position - source;
415 if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
416 /*
417 * changes the opcode of the jump instruction, in order to
418 * be able to find it later (see resizeInstructions in
437 } else {
438 offset = position + source + 1;
439 data[reference++] = (byte) (offset >>> 24);
440 data[reference++] = (byte) (offset >>> 16);
441 data[reference++] = (byte) (offset >>> 8);
442 data[reference] = (byte) offset;
443 }
444 }
445 return needUpdate;
446 }
447
448 /**
449 * Returns the first label of the series to which this label belongs. For an
450 * isolated label or for the first label in a series of successive labels,
451 * this method returns the label itself. For other labels it returns the
452 * first label of the series.
453 *
454 * @return the first label of the series to which this label belongs.
455 */
456 Label getFirst() {
457 return !ClassReader.FRAMES || frame == null ? this : frame.owner;
458 }
459
460 // ------------------------------------------------------------------------
461 // Methods related to subroutines
462 // ------------------------------------------------------------------------
463
464 /**
465 * Returns true is this basic block belongs to the given subroutine.
466 *
467 * @param id
468 * a subroutine id.
469 * @return true is this basic block belongs to the given subroutine.
470 */
471 boolean inSubroutine(final long id) {
472 if ((status & Label.VISITED) != 0) {
473 return (srcAndRefPositions[(int) (id >>> 32)] & (int) id) != 0;
474 }
475 return false;
476 }
477
|
372 System.arraycopy(srcAndRefPositions, 0, a, 0,
373 srcAndRefPositions.length);
374 srcAndRefPositions = a;
375 }
376 srcAndRefPositions[referenceCount++] = sourcePosition;
377 srcAndRefPositions[referenceCount++] = referencePosition;
378 }
379
380 /**
381 * Resolves all forward references to this label. This method must be called
382 * when this label is added to the bytecode of the method, i.e. when its
383 * position becomes known. This method fills in the blanks that where left
384 * in the bytecode by each forward reference previously added to this label.
385 *
386 * @param owner
387 * the code writer that calls this method.
388 * @param position
389 * the position of this label in the bytecode.
390 * @param data
391 * the bytecode of the method.
392 * @return <tt>true</tt> if a blank that was left for this label was too
393 * small to store the offset. In such a case the corresponding jump
394 * instruction is replaced with a pseudo instruction (using unused
395 * opcodes) using an unsigned two bytes offset. These pseudo
396 * instructions will be replaced with standard bytecode instructions
397 * with wider offsets (4 bytes instead of 2), in ClassReader.
398 * @throws IllegalArgumentException
399 * if this label has already been resolved, or if it has not
400 * been created by the given code writer.
401 */
402 boolean resolve(final MethodWriter owner, final int position,
403 final byte[] data) {
404 boolean needUpdate = false;
405 this.status |= RESOLVED;
406 this.position = position;
407 int i = 0;
408 while (i < referenceCount) {
409 int source = srcAndRefPositions[i++];
410 int reference = srcAndRefPositions[i++];
411 int offset;
412 if (source >= 0) {
413 offset = position - source;
414 if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
415 /*
416 * changes the opcode of the jump instruction, in order to
417 * be able to find it later (see resizeInstructions in
436 } else {
437 offset = position + source + 1;
438 data[reference++] = (byte) (offset >>> 24);
439 data[reference++] = (byte) (offset >>> 16);
440 data[reference++] = (byte) (offset >>> 8);
441 data[reference] = (byte) offset;
442 }
443 }
444 return needUpdate;
445 }
446
447 /**
448 * Returns the first label of the series to which this label belongs. For an
449 * isolated label or for the first label in a series of successive labels,
450 * this method returns the label itself. For other labels it returns the
451 * first label of the series.
452 *
453 * @return the first label of the series to which this label belongs.
454 */
455 Label getFirst() {
456 return frame == null ? this : frame.owner;
457 }
458
459 // ------------------------------------------------------------------------
460 // Methods related to subroutines
461 // ------------------------------------------------------------------------
462
463 /**
464 * Returns true is this basic block belongs to the given subroutine.
465 *
466 * @param id
467 * a subroutine id.
468 * @return true is this basic block belongs to the given subroutine.
469 */
470 boolean inSubroutine(final long id) {
471 if ((status & Label.VISITED) != 0) {
472 return (srcAndRefPositions[(int) (id >>> 32)] & (int) id) != 0;
473 }
474 return false;
475 }
476
|