<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <font size="4" face="monospace">Note that the "side value" concept
      is essentially a way to upgrade Java's parameter-passing protocol
      to something more like Scala's implicits, where each method has
      two argument lists, one derived from types and one consisting of
      pure runtime values.  Compiler architects would love to have such
      a translation mechanism :)</font><br>
    <br>
    <div class="moz-cite-prefix">On 6/25/2025 3:20 PM, John Rose wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:1E49739E-8E62-42E1-9330-E0E5265DFCE2@oracle.com">
      <pre wrap="" class="moz-quote-pre">On 2 Jun 2025, at 5:00, Remi Forax wrote:

</pre>
      <blockquote type="cite">
        <pre wrap="" class="moz-quote-pre">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
</pre>
      </blockquote>
      <pre wrap="" class="moz-quote-pre">
What I see here, relative to the Big Document I wrote a while ago,
is similar in some essentials, and an experiment to remove some
features that might turn out to be non-essentials.

The main removal is “split boundaries” in the constant poll.
That is, constants do not participate in wiring reification data.
Instead, reification data is injected into generics by sending
an optional extra argument, on the JVM stack.

The JIT has much less of a guarantee that such an injected value
is constant, compared to a design that is locked inside the CP.
But it might work out.  It’s worth looking at.

Another removal is built-in support for raw types.  That might work,
or we might find ourselves forced to add it back in.  “They are cute
when they are small” is a design anti-pattern.

I would encourage you to use common terminology with the Big Document
when possible, and specifically with the concept of an “anchor”.
An anchor is an implementation artifact, local to a specializable
class.  The specializable class knows how to build an anchor for
itself, and provisions the anchor with any derived metadata.
For example, an anchor for specialized ArrayList<T> might have
a way to compute List<T> (the interface) and the array T[]
(in the implementation).

IMO ACC_SIDE_VALUE should be merged into ACC_PARAMETRIC.
The distinction is too minor, IMO, for the design to give
different names to what is essentially the same condition,
appropriately applied to methods and/or classes.  One evidence
of this is that use cases nearly always turn out to require
both conditions in tandem.  That’s because you usually find
classes and methods (with constructors!) operating in tandem,
not isolated from each other.  If a class is parametric,
probably it is artificial to have none of its methods or
constructors be parametric!

The optional extra argument passed to the new bytecodes is either
an anchor (per se) or a symbolic request for an anchor which the
specializable class creates for itself (with a bootstrap method).

There is no way for a client of ArrayList to know what needs to
be inside the anchor used in the implementation of an ArrayList
specialization.  The client needs to (a) pass a simplified
“anchor specifier”, or (b) make a static call to ArrayList which
asks the ArrayList implementation to create an anchor; the
caller of ArrayList can store that anchor, as an opaque value,
in a condy.

The anchor is asymmetrically received into the generic code
(which needs it to do “stuff”) by intrinsic functions, one
for instances (of specialized instances) and one for stack
frames (of specialized calls).  (“Asymmetrically” because
it was injected by a normal push, /ldc/ or the like.)

The VM needs special permission to peek at a class anchor
to derive layout information; this is covered nicely I think.

Condy works well when you are passing from non-generic to generic
code.  It fails (unless you have Big Document split constant
pools!) for generic-to-generic calls, where an input T is
used to recursively select additional generics (like T[]
or List<T> or Arrays::<String>sort calling a subroutine).

For generic-to-generic calls, you want some way to hang
downstream anchors derived from an anchor provided to the
caller, or its caller, etc.  A heavy classfile expansion
(duplication) step could do this.  Avoiding that step
was one motivation for the Big Document split CPs.

The two kinds of generics, methods and classes, are
so very closely aligned that I recommend making even
this reduced design preserve the close alignment.
To this end, I suggest introducing one new prefix
bytecode /parametric/ which uniformly applies before
/new/ and the /invoke*/ bytecodes.  Maybe eventually
(if the design grows) /getfield/ etc.  Wherever
the Big Document calls for a parametric CP entry,
and a bytecode that uses such a CP entry, you will
encounter some pressure to introduce the /parametric/
prefix to manage the same degrees of freedom
outside the constant pool.

This extremely reduced design would probably work well
for extremely reduced use cases.  Whether it scales
well for Arrays::sort and complex generic hierarchies,
and whether the JIT can “see all the constants”, are
open questions to be evaluated.

HTH

</pre>
      <blockquote type="cite">
        <pre wrap="" class="moz-quote-pre">
---


# 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.
</pre>
      </blockquote>
    </blockquote>
    <br>
  </body>
</html>