LWorld1 initial phase proposal
Karen Kinnear
karen.kinnear at oracle.com
Wed Dec 13 19:58:01 UTC 2017
Folks,
Based on Dan Smith’s write-up: http://cr.openjdk.java.net/~dlsmith/values-notes.html of a possible
LWorld direction, we’ve written a proposal for a potential initial LWorld1 prototype and would appreciate review.
We can walk through at our next meeting Dec 20th.
JVM Lworld Value Types Phase I
http://cr.openjdk.java.net/~dlsmith/values-notes.html
I. New terminology: for LWorld
L-Type as reference or value type
Q-Type as value type
R-Type as reference only - open question - do we need this?
II. Assumptions:
1. New root: LObject - for all references and value types
2. Value Type characteristics:
immutable (not all the way down)
not nullable
no identity
flattenable when contained in reference, value type or array
no default box (buffer, not box)
- if you want identity, create a reference storing a value type field
support interfaces
III. goals:
existing interfaces should be implementable by both references and value types
- without requiring recompilation
existing code should be able to handle both references and value type arguments
- without requiring recompilation
Migration:
LType -> QType migration
author must opt-in: by declaring in source (language policy)
- requires recompilation
Any existing class that meets the requirements could become a value type
ValueBasedClasses are candidates
LWorld Value Type Static restrictions (for javac)
j.l.Object as the only superclass
no use of identity:
no use of Object methods invalid for value types: wait/notify*/finalize
no assumptions of nullability
no non-private constructors
no use of reference-only bytecodes: new, putfield, monitorenter/exit, aconst_null
LWorld Static restrictions (for verifier) TBD
no use of reference-only bytecodes: new, putfield, monitorenter/exit, aconst_null
LWorld new Dynamic restrictions (based on dynamic type)
for Value Types: no use of reference-only bytecodes: new, putfield, monitorenter/exit, aconst_null
for Reference Types: no use of value-type-only bytecodes: vdefault, withfield
no use of if_acmpeq/ne without following .equals call
IV: Non-goals:
Primitives as value types - future phase
V. Expected Behaviors:
1. Object methods
wait/notify/etc: if QType: throw ICCE (IncompatibleClassChangeError)
getClass: normal behavior (no ambiguity with no default box)
toString: nothing special
clone: nothing special (must implement cloneable)
finalize: ICCE
equals: if QType - component-wise equals (ucmp API? ucmp bytecode?) (overridable)
hashcode: TBD - needs to be based on equals
2. Java level APIs
isValue
isFlattened (for a reflection Field or array)
isElementValue (for an array - not the same as is the array a Value)
ucmp - substitutability check (not overridable)
3. Support beyond MVT
Allow Value Types in static fields (not flattened)
Method and method invocation support
Interface support: default methods - must handle both L-types and Q-types
4. LWorld bytecodes vs. JVMS 9
Key Challenge: can we apply the same bytecodes to QTypes and RTypes? can they check dynamically without loss of performance?
special handling:
if_acmpeq/if_acmpne: false/true if either is a Qtype. They should fall back to .equals
ifnull/ifnonnull: as if acmp vs. Null: false/true if QType
needs dynamic different handling:
aaload/aastore: handle LType or QType dynamically
aload/astore: handle LType or QType dynamically
areturn: handle LType or QType dynamically
exception if wrong kind: ICCE
putfield: QType exception: ICCE
monitorenter/exit: exception for QType: ICCE
new: exception for QType: ICCE (expects uninitialized state)
aconst_null: exception for QType: ICCE
vdefault: exception for LType: ICCE
withfield: exception for LType: ICCE
unchanged or already implemented (in MVT) or should fall out:
getfield: handle LType or QType dynamically (already implemented)
newarray/etc.: handle LType or QType dynamically (already implemented)
athrow: always LType (subtype of Error) - unchanged
invoke*: handle LType or QType dynamically (should fall out)
checkcast/instanceof: should fall out
ldc: should fall out
V. Implementation use of explicit QType
1. Field descriptors
Goal: not require verifier or class file parser to load all fields.
ICCE if misclaimed, at first runtime mismatch (kind constraints)
To allow flattening, want field and arrays to explicitly use QTypes at language level
2. Array descriptors: propose - yes
Remi: not needed - at array creation you know the element type
Propsal: uniformity
- confusing to explain inconsistency
- javac already knows the information and has done the work, why slow down?
- safety - kind constraints - could be checked by verifier
3. Method descriptors : propose - no
1) No indication of receiver type
2) method descriptor parameters/return type - all use LTypes
Propose: do NOT support QTypes in Method Descriptors
challenge: descriptor mismatches based on migration
- for client inheritance/overriding, caller/callee matching
Resolved Questions for LWorld1
1. Q: support other superclasses?
A: QType has no subclasses
A. for now - QType has only jlO as superclass, may be extended in future
(see if any that would break any optimizations)
2. Q:acmp behavior options:
a) failing: return false <- propose for try 1
b) throw exception
c) field-equality using ucmp as "substitutable" - field-wise comparison
general bit equality including floating point
may need to recurse on values buffereed
A: LWorld1: if >= one operand is a QType: if_acmpeq -> false, if_acmpne -> true
A: null handling: as if acmp vs. NULL
if operand is a QType: ifnull -> false, ifnonnull->true
3. Q: Do we need to know if an LType is an old L-Type or a new LType?
A: be on the lookout - we have not yet identified any cases
- note: If we do, we have ClassFileVersion
4. Q: Any issues with argument passing/argument return handling if we have
runtime mismatches of kind?
A: If we have kind constraints then we should not get runtime mismatches
A: advanced error handling - check implications if verification is skipped
5. Q: Do we need a new carrier type?
A: TBD - so far requirement not identified.
6. Q: What does it mean for LObject to be more like an interface?
A: TBD (TODO - ask Dan?)
A1. disallow adding fields
A2. superclass of references and value types (with modified methods)
7. Q: Do we need a fast way to distinguish an LType from a QType? in the JVM itself?
A. Initial prototype can work with instancKlass vs. valueKlass
Later - look at potential optimizations
8. Q: What does updated Object.hashcode do?
- field equality based hashcode
- assume cache in header optimization ?
A: Dan: call hashcode or identity hashcode (throw) - performance tradeoff
9. Q: Do we need a fast way for Java to determine ValueType (isValue call?)
A: Frederic proposed: e.g. give all value types a common super interface
e.g. ValueMarker
- verifier or class file format checking at class loading
- ensure that this can't be a superinterface if not a value type
- this is probably temporary, but useful
10. Q: Migration QType->LType support?
Customers will try this
A: Need to ensure we catch failures
challenges:
instance creation:
value type - must have a private constructor - so new will fail IAE
- except for nestmates (dynamically added which are not same compilation)
- except Reflection.setAccessible
11. Q: Circularity handling for Field types?
A: today we get StackOverflowError - hotspot folks propose we leave that alone
to avoid complexity and costly testing
12. Q: Class.forName() and internal loaded class cache
A: NO L vs. Q type naming here, there is no ambiguity
Unresolved Questions for LWorld1
1. Q: Reflection requirements/plans?
2. Q. What can the verifier check, what do we want to check later to avoid early class loading?
A. Expect to create kind constraints, if we have bytecodes that require a value type
which would be checked when we load that value type and throw ICCE
A. Verifier can still check primitive vs. LType - leave those checks in
A. note: for loaded classes such as supertypes, value type fields or isAssignable checks, some classes are already loaded, so may not need a kind constraint
Q: Do we also need to do this for references - e.g. "new" bytecode?
Q: Is there a concern that by loading a class that uses the wrong bytecodes for someone else's kind - that could prevent a class from successfully loading?
===================
Early experiment:
Add to JDK 11 (not MVT specific)
add dynamic checks for ValueBasedClasses
follow LWorld dynamic restrictions
add checks for ifacmp_eq/ne NOT followed by a call to .equals?
(todo: find Dan's corpus search results email)
todo: consider using JFR? This will be open in jdk11
Experimental steps:
1. new repo - remove MVT parts, just include -XX:+EnableValhalla tests (already split)
2. LangTools:
2.1 test bytecode generator
- generate LWorld bytecodes (from simp
2.2 Javac:
__ByValue for class declaration (for simplified JVMS bytecode changes document)
request:
super as java.lang.Object
generate LWorld bytecodes
LWorld restrictions checking
- e.g. allow superinterfaces , allow value types in static fields
2.2 new static utility class for new bytecodes
isValue
isElementValue (for array)
isFlattened (for field or array)
ucmp
2.3 java.lang.Object methods
Using isValue - rewrite
2.4 real JVMS LWorld1 proposal - Dan
3. Runtime
a. write up simplified JVMS bytecode changes document (not verifier yet)
b. interpreter bytecode changes - see list above
c. migrate VVT tests to LVT1
d. verifier -
propose JVMS verifier changes
propose kind constraint handling - to not add any additional
class loading
- note: value type fields, supertypes and isAssignable checks already perform loading
e. method handle support
4. JIT:
a. bytecodes
b. migrate VVT tests to LVT1
c. adaptor generation
d. optimizations
5. Core libraries:
a. methodhandle support - e.g. changes to LambdaForms
- (simplified from MVT with no __Value)
- no boxing
b. Reflection/new reflection?
TODO - what are the requirements here?
6. Migration testing:
Try VBC -> value type -- run tests and see what breaks
More information about the valhalla-spec-observers
mailing list