It seems to me that the rational thing to do is, in SE 11, to implicitly
assume max-depth is zero, and be done. (IE, pretend to implement this
proposal, but don't actually allow classfiles to have the attribute.)
Then we won't get any classfiles that have cycles, and the full spectrum
of cycle-accepting approaches is still on the table.
This proposal is essentially about *enabling* recursive constants in the
classfile; one would not need a RC attribute if one has no
self-reference in the CP. But allowing cycles merely creates a bigger
problem down the road -- how should bytecode readers present such a
recursive constant using the symbolic reference API? You can't
construct such a thing with the API we have, and that's by design; the
API has been designed to be value-based (and let compilers intern away
the duplication). So allowing controlled cycles in the classfile still
doesn't address the question of how to build a symbolic reference for
them. The result will probably be classfiles that blow up when you try
to parse them -- not good.
What use cases are we really concerned about here? I may have missed
the meeting where these cases were brought up, but it feels a little bit
like we're extrapolating from a single example (or maybe a single
Future<Example>).
On 1/19/2018 3:11 PM, Dan Smith wrote:
We had the following discussion in the Dec 20 meeting:
On Jan 3, 2018, at 9:11 AM, Karen Kinnear <karen.kinn...@oracle.com
<mailto:karen.kinn...@oracle.com>> wrote:
Dan S: Cycle handling
Array types can have cycles
- rather than relying on ordering - perhaps tell tree depth - e.g.
component type & dimensions - all in the CP
John: perhaps modify to include the depth indicators in an attribute
(separate proof of acyclicity)
Remi: but if you insert a condy …
John: would need to discard the attribute
Dan H: concern about a constant array for each dimension
? maybe some adhoc compression techniques
Remi: why do you want to be cycle free?
Dan S: hard to verify if types cyclical?
Remi: why do you need to check in the verifier?
John: maybe a structural constraint?
Remi: if value - ok, but not for an array of values?
e.g. Object[] with first entity as itself
Dan: want array type convertible to finite string, benefit of
attribute not tied to construct is it can evolve
Dan H: Concerns about attributes - will this be as hard to maintain
for e.g. class redefiners/bytecode generators as stackmaptables?
No - you have to keep the CP indices in sync, but stackmaptables
required abstract interpretation - transformer
did not have the type information, and the compression mechanism was
harder to implement and these
would just require bumping indices.
To flesh the attribute idea out, here's a possible spec. Mentions
CONSTANT_Dynamic for now, and would be modified in the future to name
other constant types that allow cycles.
Is this a happy solution to the problems raised in previous
discussions about constant cycles? Any new problems introduced?
—Dan
4.7.28 The `RecursiveConstants` Attribute (new)
-----------------------------------------
The `RecursiveConstants` attribute is a variable-length attribute in
the `attributes` table of a `ClassFile` structure ([4.1]). The
`RecursiveConstants` attribute facilitates checks that a
`CONSTANT_Dynamic` entry in the `constant_pool` table does not refer,
directly or indirectly, to itself ([4.4.13]).
~~~~
RecursiveConstants_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 num_recursive_constants;
{ u2 constant_index;
u2 max_recursion_depth;
} recursive_constants[num_recursive_constants];
}
~~~~
The items in the `RecursiveConstants_attribute` structure are as follows:
`attribute_name_index`
: The value of the `attribute_name_index` item must be a valid index
into the `constant_pool` table. The `constant_pool` entry at that
index must be a `CONSTANT_Utf8_info` structure ([4.4.7]) representing
the string `"RecursiveConstants"`.
`attribute_length`
: The value of the `attribute_length` item indicates the length of the
attribute, excluding the initial six bytes.
`num_recursive_constants`
: The value of the `num_recursive_constants` item gives the number of
entries in the `recursive_constants` array.
`recursive_constants`
: Each entry in the `recursive_constants` table contains the following
two items:
`constant_index`
: The value of `constant_index` must be a valid index into the
`constant_pool` table. The `constant_pool` entry at that index must be
a `CONSTANT_Dynamic` structure ([4.4.13]).
There may be at most one entry in the `recursive_constants`
table for each `CONSTANT_Dynamic` structure in the `constant_pool`.
`max_recursion_depth`
: The value of `max_recursion_depth` designates a _maximum
recursion depth_ for the referenced constant.
4.4.13 The `CONSTANT_Dynamic_info` Structure (modified)
--------------------------------------------
The `CONSTANT_Dynamic_info` structure is used to describe a
_dynamically-computed constant_, an arbitrary primitive or reference
value produced by invocation of a _bootstrap method_ ([4.7.23]). The
structure specifies i) a bootstrap method handle with an optional
sequence of _static arguments_ and ii) a referenced name and type.
~~~~
CONSTANT_Dynamic_info {
u1 tag;
u2 bootstrap_method_attr_index;
u2 name_and_type_index;
}
~~~~
The items of the `CONSTANT_Dynamic_info` structure are as follows:
`tag`
: The `tag` item of the `CONSTANT_Dynamic_info` structure has the value
`CONSTANT_Dynamic` (17).
`bootstrap_method_attr_index`
: The value of the `bootstrap_method_attr_index` item must be a valid
index into the `bootstrap_methods` array of the bootstrap method table
([4.7.23]) of this class file.
**The _maximum recursion depth_ of a `CONSTANT_Dynamic` structure
is the value given by `max_recursion_depth` of an entry referencing
the `CONSTANT_Dynamic` structure in the `recursive_constants` table of
the `RecursiveConstants` attribute ([4.7.28]); or, if no such entry
exists, 0. Let _d_ be the maximum recursion depth of this
`CONSTANT_Dynamic_info` structure. For each item in the
`bootstrap_arguments` array of the `bootstrap_methods` entry
referenced by `bootstrap_method_attr_index`, if the item references a
`CONSTANT_Dynamic_info` structure, the maximum recursion depth of that
structure must be less than (and not equal to) _d_.**
> **This check prevents a `CONSTANT_Dynamic_info` structure from
referring to itself via one of its static arguments.**
`name_and_type_index`
: The value of the `name_and_type_index` item must be a valid index
into the `constant_pool` table. The `constant_pool` entry at that
index must be a `CONSTANT_NameAndType_info` structure ([4.4.6])
representing a name and field descriptor ([4.3.2]).