|
507 | 507 | boolean enableSpecializationIntrospection() default false; |
508 | 508 |
|
509 | 509 | /** |
510 | | - * Sets the default value that {@link BytecodeLocal locals} return when they are read without |
511 | | - * ever being written. Unless a default local value is specified, loading from a |
512 | | - * {@link BytecodeLocal local} that was never stored into throws a |
| 510 | + * Specifies the default value produced when attempting to load a cleared {@link BytecodeLocal |
| 511 | + * local} (i.e., a local that has not been written to). |
| 512 | + * <p> |
| 513 | + * This attribute is mutually exclusive with {@link #illegalLocalException()}: the interpreter |
| 514 | + * can either produce a default value or throw a user-provided exception when loading a cleared |
| 515 | + * local. If neither is explicitly specified, the interpreter defaults to throwing a |
513 | 516 | * {@link FrameSlotTypeException}. |
514 | 517 | * <p> |
515 | 518 | * It is recommended for the default local value expression to refer to a static and final |
|
534 | 537 | */ |
535 | 538 | String defaultLocalValue() default ""; |
536 | 539 |
|
| 540 | + /** |
| 541 | + * Specifies the exception to throw when attempting to load a cleared {@link BytecodeLocal |
| 542 | + * local} (i.e., a local that has not been written to). |
| 543 | + * <p> |
| 544 | + * This attribute is mutually exclusive with {@link #defaultLocalValue()}: the interpreter can |
| 545 | + * either produce a default value or throw a user-provided exception when loading a cleared |
| 546 | + * local. If neither is explicitly specified, the interpreter defaults to throwing a |
| 547 | + * {@link FrameSlotTypeException}. |
| 548 | + * <p> |
| 549 | + * When an illegal local exception is specified, the interpreter checks if a local is cleared |
| 550 | + * before each load; if the local is cleared, the interpreter creates and throws an instance of |
| 551 | + * the exception using the factory method. The interpreter will attempt to |
| 552 | + * {@link #enableQuickening() quicken} away the clear check when possible. |
| 553 | + * <p> |
| 554 | + * Below is an example: |
| 555 | + * |
| 556 | + * <pre> |
| 557 | + * @GenerateBytecode(..., illegalLocalException = MyIllegalLocalException.class) |
| 558 | + * abstract class MyBytecodeRootNode extends RootNode implements BytecodeRootNode { |
| 559 | + * // ... |
| 560 | + * } |
| 561 | + * |
| 562 | + * class MyIllegaLocalException extends AbstractTruffleException { |
| 563 | + * public static MyIllegalLocalException create(Node location, BytecodeNode bytecode, BytecodeLocation location, LocalVariable variable) { |
| 564 | + * // ... |
| 565 | + * } |
| 566 | + * } |
| 567 | + * </pre> |
| 568 | + * |
| 569 | + * The provided exception class must declare a static factory method for instantiating |
| 570 | + * exceptions. By default, this method is named {@code create}, but this can be overridden using |
| 571 | + * {@link #illegalLocalExceptionFactory()}. |
| 572 | + * <p> |
| 573 | + * The factory method should return an instance of the exception class. It may take zero or more |
| 574 | + * parameters of the following types (in any order): |
| 575 | + * <ul> |
| 576 | + * <li>{@link Node}: the current location (equivalent to {@code @Bind("$node")})</li> |
| 577 | + * <li>{@link BytecodeNode}: the current bytecode node</li> |
| 578 | + * <li>{@link BytecodeLocation}: the current bytecode location</li> |
| 579 | + * <li>{@link LocalVariable}: an introspection object modeling the local's metadata (name, info, |
| 580 | + * etc.)</li> |
| 581 | + * </ul> |
| 582 | + * |
| 583 | + * <p> |
| 584 | + * If the provided exception class is a Truffle exception (i.e., it extends |
| 585 | + * {@link com.oracle.truffle.api.exception.AbstractTruffleException}), the exception can be |
| 586 | + * thrown from runtime compiled code without deoptimization; otherwise, it is considered an |
| 587 | + * internal error and throwing the exception will always trigger deoptimization. |
| 588 | + * <p> |
| 589 | + * Note: due to current limitations of the Bytecode DSL implementation, illegal local exceptions |
| 590 | + * are not yet fully supported with local accessors: |
| 591 | + * <ul> |
| 592 | + * <li>If an operation uses a {@link LocalAccessor} or {@link LocalRangeAccessor}, the factory |
| 593 | + * method cannot declare a {@link BytecodeLocation} parameter.</li> |
| 594 | + * <li>If an operation uses a {@link MaterializedLocalAccessor}, illegal local exceptions cannot |
| 595 | + * be used.</li> |
| 596 | + * </ul> |
| 597 | + * |
| 598 | + * @since 25.1 |
| 599 | + */ |
| 600 | + Class<? extends RuntimeException> illegalLocalException() default FrameSlotTypeException.class; |
| 601 | + |
| 602 | + /** |
| 603 | + * Specifies the name of the static factory method used to instantiate illegal local exceptions. |
| 604 | + * This attribute is only applicable if an {@link #illegalLocalException()} class is specified. |
| 605 | + * |
| 606 | + * @see #illegalLocalException() |
| 607 | + * @since 25.1 |
| 608 | + */ |
| 609 | + String illegalLocalExceptionFactory() default "create"; |
| 610 | + |
537 | 611 | /** |
538 | 612 | * Whether the {@link BytecodeDebugListener} methods should be notified by generated code. By |
539 | 613 | * default the debug bytecode listener is enabled if the root node implements |
|
0 commit comments