Draft LW2 spec

Dan Smith daniel.smith at oracle.com
Tue Jun 25 00:10:29 UTC 2019


> On Jun 20, 2019, at 8:23 AM, Karen Kinnear <karen.kinnear at oracle.com> wrote:
> 
> 1. Versioning
> Thank you for asking.
> For LW10, we plan to use preview versioning. For LW2, we just use JDK13 cfv 57

Fixed now in my local copy (which I'll share soon).

> 2. 2.4 Reference Types and Values
> Bullet defining Array component type
> "the element type of a multi-dimensional array is the element type of its component type"
> - it is no longer clear that the element type is not the next dimension down, but the
> final one that is not itself an array

How's this?

    Every array type has a non-array *element type*.
    The element type of a single-dimensional array type is its component type;
    the element type of a multi-dimensional array type is the element type of
    its component type (applying this definition recursively).**

> 3. 4.4.1 The CONSTANT_Class_info Strtucture
> "In a class file whose version number is not 57.65535, the name_index item must not be a field descriptor of the form NullableClassType or NullFreeClassType."
> 
> Actually, since NullableClassType replaced ClassType - isn't it just NullFreeClassType that is not ok?

There are three forms of name_index values:

Foo
LFoo;
QFoo;

The latter two are new in 57.0.

See the design discussion later in this section:

"The strategy used here is to overload CONSTANT_Class_info with null-free class type descriptors. In doing so, there's no particular reason (though we may decide to be more restrictive) that L types can't be supported, too, as an alternative to bare class names in contexts that work on arbitrary types. The only descriptors that can't be allowed, due to syntactic ambiguity, are those for primitive types—supporting primitive types would require new syntax."

> 4. 4.6. Methods
> name_index
> "The value of the 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 either a valid unqualified name denoting a method (4.2.2), or (if this method is in a class an identity class or the Object class rather than an inline class or an interface) the special method name <init>, or the special method name <clinit>."
> 
> — LW2 was changed: now have <init> for inline classes. We also have <clinit>.

I'll work on <init>. Probably will spin it off into a separate document, because it's an orthogonal feature.

The sentence is meant to allow for <clinit> in all cases. It's just phrased awkwardly.

> 5a. 5.4.3.1 Class, Interface and Reference Type Resolution
> Any attempt to resolve a reference to a null-free inline type, that resolves to a non-inline type,
> throws an ICCE at resolution time.
> 
> For example, this is used by 6.5 defaultvalue.
> 
> I would assume you want to put this in 5.4.3.1, but you could put this in 6.5 defaultvalue.
> The implementation puts this in 5.4.3.1 equivalent. 

I put this check in preparation for field/method declarations, but didn't touch other places Q types may appear.

I've added it to 5.4.3.1 (Q type as CONSTANT_Class), 5.4.3.3 (Q type in signature-polymorphic method descriptor), and 5.4.3.5 (Q type in CONSTANT_MethodType) in my local copy. The requirement here is that we never try to create a java.lang.Class (or similar internal class object) representing, for example, Qjava/lang/String;.

There are also Q types in field and method references. I'm tentatively thinking that mismatches here are harmless, because they'll just result in lookup failures (no field/method with a bad descriptor can be declared). Agreed, or do we want a check somewhere?

> 5b. 4.9.1. Static Constraints
> "Every defaultvalue instruction must reference a constant pool entry of kind CONSTANT_Class that represents a null-free class type.”
> 
> In anticipation of evolution of defaultvalue to handle null-default inline types, and possibly
> to handle nullable inline types, and in an effort to not add additional eager loading for
> the verifier, for LW2, we removed the verifier checks for defaultvalue enforcing a null-free class type and moved the check to runtime.and new bytecodes relative to null-free and inline classes.

"represents a null-free class type" is a constraint on the syntax, not on the properties of the referenced class. So: every defaultvalue must point to a CONSTANT_Class of the form 'Q...;'. Does that line up with what has been implemented?

(For more discussion on why I think we don't want bare class names here, see the 'defaultvalue' spec in 6.5.)

> 6. 5.4.2. Preparation (discussion topic for EG)
> 
> Part I: Method descriptors:
> JVMS LW2 draft specifies that the declared method ptypes marked as null-free are loaded
> as part of preparation, including throwing ICCE if not an inline class.
> 
> We have had previous discussions with IBM - I think we want some verbiage to allow eager or
> lazy resolution of method ptypes which are null-free inline types.
> 
> Hotspot needs to load these as part of linking (we can discuss if this is part of preparation or not later)
> IBM wants to lazily load at first invocation
> 
> We all agree on ICCE for a mismatch here.

Hmm, I'll have to think about where to put this, if not in preparation. I'm sad to give up on "During preparation of a class or interface C, the Java Virtual Machine imposes constraints on field and method descriptors (4.3)"—it seems like a natural fit for all these checks. But if it's important to be able to delay checking Q types in method descriptors, we can probably find a way to specify it.

> Part II. Field Descriptors: Instance Fields
> This has to be performed at load time/class definition time - needed for layout.
>   - Not at preparation time - that is too late.
> 
> I believe we do agree with ICCE and risk of ClassCircularityError if “flattenable”.

Same comment—preparation is a nice fit, class creation less so, but if it's what we need I'll see what I can do.

> Part III. Field Descriptors: Static Fields
> 
> For LW2, for static fields, we do the same exercise as we do for instance fields,
> with the same risk of ICCE and ClassCircularityError.
> 
> See below for potential post-LW2 static field open issue.

Ok, fixed in my local copy.

> 7. putfield:
> Needs updating - now that inline classes support <init> - putfield is
> not supposed to modify inline class instance fields, even during <init>
> (being a final field is not sufficient to stop that) - so need IAE
> if resolved field is a field of an inline class.
> We don't want verifier to catch since this should apply to both LPoint; and QPoint;

The verifier needs some awareness of this, too, because of the special typing rules for unitializedThis.

I think it's straightforward to fix up, and comes down what we mean by "instance initialization method", which is currently interpreted as "method named '<init>'", but can have some additional constraints.

> post-LW2, design discussion comments:
> 
> 1. 6.5. monitorenter
> What is the Design discussion proposing?
> Would love a solution for this - have not found one that is satisfactory.

Not proposing anything new! Just trying to document the existing unresolved discussion, if I'm reading where we're at on this correctly.

If we want to do something more than throw for an inline class instance, I think what it looks like is basically interning: use a hash table to map instances that are equivalent to a canonical object, except in this case "equivalent" means acmp and the canonical object is a lock rather than another class instance.

> Karen’s concern - about accidental sharing of the same monitor
> -in the field surprise bugs - hard to reproduce - timing based
> - e.g. I try to lock but you are holding the lock (but we are running completely independent code)
>   e.g. overlap for wait and notify (customers do not always check conditions for notify)


Okay, so this is what you mean by not "satisfactory". You don't like "unique" objects held by different people to share the same lock. Which is reasonable to be uncomfortable about, but I also think having no identity means it's a bug to think your object is "unique". Whether this is a bigger violation of user expectations than the behavior of acmp, which also can introduce bugs when users assume uniqueness, is worth more exploration.

> 2. 5.4.2 Preparation
> Post-LW2 we need to have a discussion on how to handle static fields that are inline types.
> There are challenges with ClassCircularityIssues even though we have agreed that in practice
> we don’t actually want to flatten static null-free inline classes. There are also issues
> with timing of default value creation relative to class load/class initialization/visibility
> of an instance on which operations can happen, since the class initialization barrier
> includes new, defaultvalue/anewarray/multianewarray which allows other bytecodes operating on instances to not have an initialization barrier.
> Frederic has been studying possible ways to deal with issues that occur due to examples such as:
> example 1: class MyValue: static MyValue; // the degenerate case
> example 2: class A: static B sb; class B: static A sa;

I'd like to understand this better. I think I'm happy with what I put in the spec document, but it may be that new issues arise when trying to shift the timing from preparation to creation.



More information about the valhalla-spec-experts mailing list