Remi Forax
forax at univ-mlv.fr
Mon Jun 2 12:00:45 UTC 2025
Hello, this is a small proposal to try start (re-start) discussions about what would be the minimal changes of the JVM spec enabling java.util collections to be specialized at runtime when value classes are used as type arguments (by example a List<LocalDate>). regards, Rémi --- # Java Virtual Machine Specification Extension: Runtime Parametric Type Support ## 1. Introduction This specification defines extensions to the Java Virtual Machine to support runtime propagation of type arguments for parametric (generic) classes and methods. While maintaining full backward compatibility with existing bytecode, these extensions enable type arguments to be available at runtime through two primary mechanisms: method call side value and parametric class instantiation. ### 1.1 Goals - Propagate type arguments at runtime while preserving type erasure compilation - Maintain complete backward compatibility with existing bytecode - Support both parametric method calls and parametric class instantiation - Provide clean APIs for accessing runtime type information ### 1.2 Overview The specification introduces: - A method modifier for method supporting side value - Reuse the opcode wide to specify method call side value - An API method "currentSideValue" to get the side value associated to a method call inside the callee - A new class modifier for parametric class - A new opcode anew_parametric for parametric Class instantiation (to send the layout + metadata) - An API method "currentMetadata" to get the metadata inside a parametric class --- ## 2. Class File Format Extensions ### 2.1 Access Flags Two new access flags are introduced: #### 2.1.1 ACC_SIDE_VALUE (new_flag) - **Applicable to**: Methods - **Purpose**: Indicates that a method accepts a side value (type arguments) from callers - **Behavior**: Enables `wide` method calls and access to `currentSideValue()` within the method #### 2.1.2 ACC_PARAMETRIC (new_flag) - **Applicable to**: Classes - **Purpose**: Indicates that a class supports parametric instantiation - **Behavior**: Enables `anew_parametric` instruction and access to `currentMetadata()` ### 2.2 Flag Validation - Methods with `ACC_SIDE_VALUE` must be declared to handle side value parameters - Classes with `ACC_PARAMETRIC` must support the `LayoutHandle` interface for instantiation - These flags are ignored by JVM implementations that do not support this extension --- ## 3. Method Call Side Value ### 3.1 Concept Method call side value enable the passing of an object (type arguments) from a call site to the callee method at runtime. This mechanism simulates generic type parameter passing without modifying method signatures. ### 3.2 Method Declaration Methods that accept a side value must be marked with the `ACC_SIDE_VALUE` access flag: ```java // Conceptual representation public static ACC_SIDE_VALUE void message(String message) { Object sideValue = currentSideValue(); ... } ``` ### 3.3 Bytecode Instructions #### 3.3.1 Wide Prefix for Method Calls The `wide` instruction is extended to prefix method call instructions when side values are passed: **Syntax:** ``` wide <method_call_instruction> ``` **Supported Instructions:** - `invokestatic` - `invokevirtual` - `invokespecial` - `invokeinterface` - `invokedynamic` #### 3.3.2 Stack Layout When using `wide` with method calls, an additional argument must be present on the stack: **Stack (top to bottom):** ``` [method arguments...] [side value (Object)] ``` **Example Bytecode:** ```bytecode ldc "TypeArgument" // Push side value ldc "hello" // Push method argument wide invokestatic Foo.message(Ljava/lang/String;)V ``` ### 3.4 Runtime Behavior #### 3.4.1 currentSideValue() Method **Signature:** `public static Object currentSideValue()` **Behavior:** - Returns the side value passed to the current method - Returns `null` if the method was called without `wide` - Must only be called within methods marked `ACC_SIDE_VALUE` **Exceptions:** - `LinkageError`: Thrown if called from a method not marked `ACC_SIDE_VALUE` #### 3.4.2 Call Resolution 1. When `wide` prefixes a method call, the JVM pops the side value from the stack 2. The side value is made available to the target method via `currentSideValue()` 3. The method call proceeds normally with remaining stack arguments 4. If the target method is not marked `ACC_SIDE_VALUE`, a `VerifyError` is thrown --- ## 4. Parametric Class Instantiation ### 4.1 Concept Parametric class instantiation allows objects to be created with associated type metadata that remains accessible throughout the object's lifetime. ### 4.2 Class Declaration Classes supporting parametric instantiation must be marked with the `ACC_PARAMETRIC` access flag and work with the `LayoutHandle` interface. ### 4.3 LayoutHandle Interface ```java public interface LayoutHandle { /** * Returns metadata associated with this layout. * Must be a pure function (no side effects, deterministic). */ Object getMetadata(); /** * Returns the restricted field type for the given field. * Must be a pure function (no side effects, deterministic). * * @param name field name * @param descriptor field descriptor * @return Restricted type information */ Restricted fieldType(String name, String descriptor); } ``` ### 4.4 anew_parametric Instruction #### 4.4.1 Specification **Opcode:** (new opcode) **Format:** ``` anew_parametric indexbyte1 indexbyte2 ``` **Stack:** - **Before:** `[layout_handle]` - **After:** `[objectref]` **Description:** Creates a new instance of the class referenced by the constant pool entry at index `(indexbyte1 << 8) | indexbyte2`. The class must be marked with `ACC_PARAMETRIC`. The `layout_handle` on the stack must implement `LayoutHandle`. #### 4.4.2 Runtime Behavior 1. Pop `layout_handle` from stack 2. Resolve class reference from constant pool 3. Verify class has `ACC_PARAMETRIC` flag 4. Create new instance of the class 5. Associate the `layout_handle` with the instance 6. Push object reference onto stack **Exceptions:** - `VerifyError`: If class is not marked `ACC_PARAMETRIC` ### 4.5 Runtime Metadata Access #### 4.5.1 currentMetadata() Method **Signature:** `public static Object currentMetadata()` **Behavior:** - Returns the metadata from the `LayoutHandle` used to create the current instance - Returns `null` if the instance was created with standard `anew` - Must only be called within classes marked `ACC_PARAMETRIC` **Exceptions:** - `LinkageError`: Thrown if called from a class not marked `ACC_PARAMETRIC` --- ## 5. Verification and Linking ### 5.1 Class File Verification #### 5.1.1 ACC_SIDE_VALUE Methods - `currentSideValue()` calls must only appear in `ACC_SIDE_VALUE` methods #### 5.1.2 ACC_PARAMETRIC Classes - `currentMetadata()` calls must only appear in `ACC_PARAMETRIC` classes ### 5.2 Linking Requirements #### 5.2.1 Method Resolution - `wide` prefixed calls must resolve to valid method references with `ACC_SIDE_VALUE` flag - Side value compatibility is checked at call time, not link time #### 5.2.2 Class Resolution - `anew_parametric` must reference classes with `ACC_PARAMETRIC` flag - `LayoutHandle` implementation must be verified at instantiation time --- ## 6. Backward Compatibility ### 6.1 Bytecode Compatibility - All existing bytecode continues to work unchanged ### 6.2 Runtime Compatibility - `currentSideValue()` returns `null` if the method is called without the `wide` prefix. - `currentMetadata()` returns `null` if the object is instantiated without `anew_parametric` --- ## 8. Examples ### 8.1 Method Call Side Value Example ```java // Method declaration (conceptual) public static ACC_SIDE_VALUE void printType(Object value) { Object typeInfo = currentSideValue(); System.out.println("Value: " + value + ", Type: " + typeInfo); } // Bytecode usage ldc String.class // Type argument ldc "Hello World" // Method argument wide invokestatic Example.printType(Ljava/lang/Object;)V ``` ### 8.2 Parametric Class Example ```java // Class declaration (conceptual) public class ACC_PARAMETRIC Container { public void setValue(Object value) { Object metadata = currentMetadata(); System.out.println("Value: " + value + ", Metadata: " + metadata); } } // Bytecode usage ldc ConstantDynamic MyLayoutHandle // Get the layout handle anew_parametric Container ``` --- ## 9. Formal Grammar Extensions ### 9.1 Method Call Instructions ``` method_call_instruction ::= [wide] (invokestatic | invokevirtual | invokespecial | invokeinterface | invokedynamic) indexbyte1 indexbyte2 wide_method_call ::= wide method_call_opcode indexbyte1 indexbyte2 ``` ### 9.2 Object Creation Instructions ``` object_creation_instruction ::= anew indexbyte1 indexbyte2 | anew_parametric indexbyte1 indexbyte2 ``` --- ## 10. Conclusion This specification extends the Java Virtual Machine to support runtime parametric type propagation while maintaining complete backward compatibility. The two-mechanism approach (method call side values and parametric class instantiation) provides comprehensive support for runtime generic type information without breaking existing code or requiring recompilation of legacy applications. The design prioritizes backward compatibility and simplicity by transfering most the burden to JITs that must propagate the side value/metadata as constants across the method call graph.
More information about the valhalla-spec-experts mailing list
Mon Jun 2 12:00:45 UTC 2025
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Hello, this is a small proposal to try start (re-start) discussions about what would be the minimal changes of the JVM spec enabling java.util collections to be specialized at runtime when value classes are used as type arguments (by example a List<LocalDate>). regards, Rémi --- # Java Virtual Machine Specification Extension: Runtime Parametric Type Support ## 1. Introduction This specification defines extensions to the Java Virtual Machine to support runtime propagation of type arguments for parametric (generic) classes and methods. While maintaining full backward compatibility with existing bytecode, these extensions enable type arguments to be available at runtime through two primary mechanisms: method call side value and parametric class instantiation. ### 1.1 Goals - Propagate type arguments at runtime while preserving type erasure compilation - Maintain complete backward compatibility with existing bytecode - Support both parametric method calls and parametric class instantiation - Provide clean APIs for accessing runtime type information ### 1.2 Overview The specification introduces: - A method modifier for method supporting side value - Reuse the opcode wide to specify method call side value - An API method "currentSideValue" to get the side value associated to a method call inside the callee - A new class modifier for parametric class - A new opcode anew_parametric for parametric Class instantiation (to send the layout + metadata) - An API method "currentMetadata" to get the metadata inside a parametric class --- ## 2. Class File Format Extensions ### 2.1 Access Flags Two new access flags are introduced: #### 2.1.1 ACC_SIDE_VALUE (new_flag) - **Applicable to**: Methods - **Purpose**: Indicates that a method accepts a side value (type arguments) from callers - **Behavior**: Enables `wide` method calls and access to `currentSideValue()` within the method #### 2.1.2 ACC_PARAMETRIC (new_flag) - **Applicable to**: Classes - **Purpose**: Indicates that a class supports parametric instantiation - **Behavior**: Enables `anew_parametric` instruction and access to `currentMetadata()` ### 2.2 Flag Validation - Methods with `ACC_SIDE_VALUE` must be declared to handle side value parameters - Classes with `ACC_PARAMETRIC` must support the `LayoutHandle` interface for instantiation - These flags are ignored by JVM implementations that do not support this extension --- ## 3. Method Call Side Value ### 3.1 Concept Method call side value enable the passing of an object (type arguments) from a call site to the callee method at runtime. This mechanism simulates generic type parameter passing without modifying method signatures. ### 3.2 Method Declaration Methods that accept a side value must be marked with the `ACC_SIDE_VALUE` access flag: ```java // Conceptual representation public static ACC_SIDE_VALUE void message(String message) { Object sideValue = currentSideValue(); ... } ``` ### 3.3 Bytecode Instructions #### 3.3.1 Wide Prefix for Method Calls The `wide` instruction is extended to prefix method call instructions when side values are passed: **Syntax:** ``` wide <method_call_instruction> ``` **Supported Instructions:** - `invokestatic` - `invokevirtual` - `invokespecial` - `invokeinterface` - `invokedynamic` #### 3.3.2 Stack Layout When using `wide` with method calls, an additional argument must be present on the stack: **Stack (top to bottom):** ``` [method arguments...] [side value (Object)] ``` **Example Bytecode:** ```bytecode ldc "TypeArgument" // Push side value ldc "hello" // Push method argument wide invokestatic Foo.message(Ljava/lang/String;)V ``` ### 3.4 Runtime Behavior #### 3.4.1 currentSideValue() Method **Signature:** `public static Object currentSideValue()` **Behavior:** - Returns the side value passed to the current method - Returns `null` if the method was called without `wide` - Must only be called within methods marked `ACC_SIDE_VALUE` **Exceptions:** - `LinkageError`: Thrown if called from a method not marked `ACC_SIDE_VALUE` #### 3.4.2 Call Resolution 1. When `wide` prefixes a method call, the JVM pops the side value from the stack 2. The side value is made available to the target method via `currentSideValue()` 3. The method call proceeds normally with remaining stack arguments 4. If the target method is not marked `ACC_SIDE_VALUE`, a `VerifyError` is thrown --- ## 4. Parametric Class Instantiation ### 4.1 Concept Parametric class instantiation allows objects to be created with associated type metadata that remains accessible throughout the object's lifetime. ### 4.2 Class Declaration Classes supporting parametric instantiation must be marked with the `ACC_PARAMETRIC` access flag and work with the `LayoutHandle` interface. ### 4.3 LayoutHandle Interface ```java public interface LayoutHandle { /** * Returns metadata associated with this layout. * Must be a pure function (no side effects, deterministic). */ Object getMetadata(); /** * Returns the restricted field type for the given field. * Must be a pure function (no side effects, deterministic). * * @param name field name * @param descriptor field descriptor * @return Restricted type information */ Restricted fieldType(String name, String descriptor); } ``` ### 4.4 anew_parametric Instruction #### 4.4.1 Specification **Opcode:** (new opcode) **Format:** ``` anew_parametric indexbyte1 indexbyte2 ``` **Stack:** - **Before:** `[layout_handle]` - **After:** `[objectref]` **Description:** Creates a new instance of the class referenced by the constant pool entry at index `(indexbyte1 << 8) | indexbyte2`. The class must be marked with `ACC_PARAMETRIC`. The `layout_handle` on the stack must implement `LayoutHandle`. #### 4.4.2 Runtime Behavior 1. Pop `layout_handle` from stack 2. Resolve class reference from constant pool 3. Verify class has `ACC_PARAMETRIC` flag 4. Create new instance of the class 5. Associate the `layout_handle` with the instance 6. Push object reference onto stack **Exceptions:** - `VerifyError`: If class is not marked `ACC_PARAMETRIC` ### 4.5 Runtime Metadata Access #### 4.5.1 currentMetadata() Method **Signature:** `public static Object currentMetadata()` **Behavior:** - Returns the metadata from the `LayoutHandle` used to create the current instance - Returns `null` if the instance was created with standard `anew` - Must only be called within classes marked `ACC_PARAMETRIC` **Exceptions:** - `LinkageError`: Thrown if called from a class not marked `ACC_PARAMETRIC` --- ## 5. Verification and Linking ### 5.1 Class File Verification #### 5.1.1 ACC_SIDE_VALUE Methods - `currentSideValue()` calls must only appear in `ACC_SIDE_VALUE` methods #### 5.1.2 ACC_PARAMETRIC Classes - `currentMetadata()` calls must only appear in `ACC_PARAMETRIC` classes ### 5.2 Linking Requirements #### 5.2.1 Method Resolution - `wide` prefixed calls must resolve to valid method references with `ACC_SIDE_VALUE` flag - Side value compatibility is checked at call time, not link time #### 5.2.2 Class Resolution - `anew_parametric` must reference classes with `ACC_PARAMETRIC` flag - `LayoutHandle` implementation must be verified at instantiation time --- ## 6. Backward Compatibility ### 6.1 Bytecode Compatibility - All existing bytecode continues to work unchanged ### 6.2 Runtime Compatibility - `currentSideValue()` returns `null` if the method is called without the `wide` prefix. - `currentMetadata()` returns `null` if the object is instantiated without `anew_parametric` --- ## 8. Examples ### 8.1 Method Call Side Value Example ```java // Method declaration (conceptual) public static ACC_SIDE_VALUE void printType(Object value) { Object typeInfo = currentSideValue(); System.out.println("Value: " + value + ", Type: " + typeInfo); } // Bytecode usage ldc String.class // Type argument ldc "Hello World" // Method argument wide invokestatic Example.printType(Ljava/lang/Object;)V ``` ### 8.2 Parametric Class Example ```java // Class declaration (conceptual) public class ACC_PARAMETRIC Container { public void setValue(Object value) { Object metadata = currentMetadata(); System.out.println("Value: " + value + ", Metadata: " + metadata); } } // Bytecode usage ldc ConstantDynamic MyLayoutHandle // Get the layout handle anew_parametric Container ``` --- ## 9. Formal Grammar Extensions ### 9.1 Method Call Instructions ``` method_call_instruction ::= [wide] (invokestatic | invokevirtual | invokespecial | invokeinterface | invokedynamic) indexbyte1 indexbyte2 wide_method_call ::= wide method_call_opcode indexbyte1 indexbyte2 ``` ### 9.2 Object Creation Instructions ``` object_creation_instruction ::= anew indexbyte1 indexbyte2 | anew_parametric indexbyte1 indexbyte2 ``` --- ## 10. Conclusion This specification extends the Java Virtual Machine to support runtime parametric type propagation while maintaining complete backward compatibility. The two-mechanism approach (method call side values and parametric class instantiation) provides comprehensive support for runtime generic type information without breaking existing code or requiring recompilation of legacy applications. The design prioritizes backward compatibility and simplicity by transfering most the burden to JITs that must propagate the side value/metadata as constants across the method call graph.
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the valhalla-spec-experts mailing list