Invoke Dynamic EDR

(Difference between revisions)

Revision as of 01:07, 6 May 2008 (edit)

John Rose (Talk | contribs | block)

m 

Previous diff

Current revision (21:33, 21 May 2008) (edit) (undo)

John Rose (Talk | contribs | block)    [rollback]

(proposed updates)

 

Line 1:

Line 1:

-

<em>JCP EDR 1.0 for Dynamic Invocation: JSR 292 Expert Group</em>

+

<em>JCP EDR 1.01 for Dynamic Invocation: JSR 292 Expert Group</em>






The following design is intended to simplify and speed dynamic language implementations. It is a draft, with some decisions marked provisional, and a number of design issues called out. The JSR 292 Expert Group believes this is the right general direction to take, and invites community comment and experimentation. During the EDR comment period we will converge on a specification that is precise, practical for JVM implementors, and helpful to language implementors. Parallel work on reference implementations will also clarify this specification.


The following design is intended to simplify and speed dynamic language implementations. It is a draft, with some decisions marked provisional, and a number of design issues called out. The JSR 292 Expert Group believes this is the right general direction to take, and invites community comment and experimentation. During the EDR comment period we will converge on a specification that is precise, practical for JVM implementors, and helpful to language implementors. Parallel work on reference implementations will also clarify this specification.

Line 63:

Line 63:


* descriptor: the formatted string (within a classfile) which determines a method&rsquo;s type descriptor, i.e., its argument and return types


* descriptor: the formatted string (within a classfile) which determines a method&rsquo;s type descriptor, i.e., its argument and return types





-

We assume the reader is familiar the design of the JVM, and of its invocation bytecodes in particular. For a detailed summary of the design of JVM call sites, the reader may find helpful this web page: http://blogs.sun.com/jrose/entry/anatomy_of_a_call_site

+

(<em>Note:</em> We assume the reader is familiar the design of the JVM, and of its invocation bytecodes in particular. For a detailed summary of the design of JVM call sites, the reader may find helpful this web page: http://blogs.sun.com/jrose/entry/anatomy_of_a_call_site )






(<em>Note:</em> Interspersed throughout this document are parenthetical asides, like this one, noting interesting aspects of this design, or pointing out remaining issues which must be resolved in order for the design to be complete. There are also code examples which illustrate the specification. These asides and examples are <em>not</em> a proper part of the specification; they do not affect compliance.)


(<em>Note:</em> Interspersed throughout this document are parenthetical asides, like this one, noting interesting aspects of this design, or pointing out remaining issues which must be resolved in order for the design to be complete. There are also code examples which illustrate the specification. These asides and examples are <em>not</em> a proper part of the specification; they do not affect compliance.)

Line 129:

Line 129:


class MethodType {


class MethodType {


/** Report a parameter type. */


/** Report a parameter type. */

-

public Class<?> parameterType(int num) {...}

+

public Class<?> parameterType(int num) throws ClassNotFoundException {...}


/** Report the number of parameter types. */


/** Report the number of parameter types. */


public int parameterCount();


public int parameterCount();


/** Report the return type. */


/** Report the return type. */

-

public Class<?> returnType() {...}

+

public Class<?> returnType() throws ClassNotFoundException {...}


/** Find or create a canonical instance of the given method type. */


/** Find or create a canonical instance of the given method type. */


public static MethodType make(Class<?> rtype, Class<?>... ptypes);


public static MethodType make(Class<?> rtype, Class<?>... ptypes);

 

+

/** Find or create a canonical instance of the given method type. */

 

+

public static MethodType make(String bytecodeSignature, ClassLoader loader);


/** Constructor is private to enforce use of interning factory method. */


/** Constructor is private to enforce use of interning factory method. */


private MethodType() {...}


private MethodType() {...}

Line 213:

Line 215:


(<em>Note:</em> When the JVM checks method types at method handle calls, it will need to perform pointer equality checks on interned <code>MethodType</code> descriptors, rather than match the sequences of argument types. This implies that method types must be interned at some point before the call. The simplest way to enforce this is to make <code>MethodType</code> be a concrete final class, with an interning factory method.)


(<em>Note:</em> When the JVM checks method types at method handle calls, it will need to perform pointer equality checks on interned <code>MethodType</code> descriptors, rather than match the sequences of argument types. This implies that method types must be interned at some point before the call. The simplest way to enforce this is to make <code>MethodType</code> be a concrete final class, with an interning factory method.)





-

For further discussion of method handles, with rationale for their design, see this web page: http://blogs.sun.com/jrose/entry/method_handles_in_a_nutshell

+

(<em>Note:</em> A method type cannot be properly represented by a mere string. The minimum requirement is a string plus a ClassLoader reference, to give a meaning to the class names embedded in the string.)

 

+

 

 

+

(<em>Note:</em> Making method types opaque may allow some JVM implementors to use them as low-level data structures to support method linkage.)

 

+

 

 

+

As with standard JVM signatures, a <code>MethodType</code> can be created, and compared with other method types for equality, before all of its component types are loaded. Asking a method type for its parameter or result type may initiate class loading. It will not (of itself) initialize the class. It may provoke a <code>ClassNotFoundException</code>. (Cf. <code>Class.forName</code>, with an initialize parameter of false.)

 

+

 

 

+

(<em>Issue:</em> Should there be a way to query class names and class loaders, which would not be vulnerable to <code>ClassNotFoundException</code>? This would add complexity to the implementation, with little apparent benefit. In practice, component classes are loaded by the time the affected methods are called, and there seems little added benefit to finding out the names of classes which fail to be loaded. Perhaps the <code>ClassNotFoundException</code> can be enhanced to report the failing lookup, or we can define a new exception just for this purpose.)

 

+

 

 

+

(<em>Note:</em> For further discussion of method handles, with rationale for their design, see this web page: http://blogs.sun.com/jrose/entry/method_handles_in_a_nutshell )






=== Types for dynamic linking: <code>Linkage</code>, <code>StaticContext</code>, <code>CallSite</code> ===


=== Types for dynamic linking: <code>Linkage</code>, <code>StaticContext</code>, <code>CallSite</code> ===

Line 219:

Line 229:


The all-static class <code>Linkage</code> provides basic routines for bootstrapping and dynamically linking call sites.


The all-static class <code>Linkage</code> provides basic routines for bootstrapping and dynamically linking call sites.





-

The interface <code>StaticContext</code> provides a channel for the JVM to inform bootstrap code of which call sites are being linked.

+

The interface <code>StaticContext</code> provides a channel for the JVM to inform bootstrap code of which call sites are being linked. A static context is immutable linkage information permanently associated with each call site. It is pure structure; its identity (as detected by reference equality) is insignificant.





-

The interface <code>CallSite</code> provides the necessary &lsquo;hook&rsquo; for bootstrap methods (or failing methods) to update the state of an <code>invokedynamic</code> instruction&rsquo;s linkage state.

+

The interface <code>CallSite</code> provides the necessary &lsquo;hook&rsquo; for bootstrap methods (or failing methods) to update the state of an <code>invokedynamic</code> instruction&rsquo;s linkage state. A call site has a single mutable variable, the target method, plus an immutable static context. The identity of a call site object (as detected by reference equality) is significant.






These types are described in more detail below.


These types are described in more detail below.

Line 293:

Line 303:


If the bootstrap method returns normally, the resulting object reference is cast and/or unboxed as necessary to conform to the descriptor of the calling <code>invokedynamic</code> instruction. The resulting value is pushed on the caller stack, and the instruction terminates normally.


If the bootstrap method returns normally, the resulting object reference is cast and/or unboxed as necessary to conform to the descriptor of the calling <code>invokedynamic</code> instruction. The resulting value is pushed on the caller stack, and the instruction terminates normally.





-

The bootstrap method may (or may not) use the <code>CallSite.setTargetMethod</code> method to install a target method on the call site. This target method will be used for future executions of the call site is executed.

+

The bootstrap method may (or may not) use the <code>CallSite.setTarget</code> method to install a target method on the call site. This target method will be used for future executions of the call site is executed.






=== Context attribute of the reified call site ===


=== Context attribute of the reified call site ===

Line 304:

Line 314:


interface StaticContext {


interface StaticContext {


/** The calling class. */


/** The calling class. */

-

Class getCallerClass();

+

Class callerClass();


/** The name specified in the invokedynamic instruction. */


/** The name specified in the invokedynamic instruction. */

-

String getName();

+

String name();


/** The resolved result and parameter types, derived from the invocation descriptor. */


/** The resolved result and parameter types, derived from the invocation descriptor. */

-

MethodType getType();

+

MethodType type();


/** Equality testing depends only on the equality of corresponding members. */


/** Equality testing depends only on the equality of corresponding members. */

-

boolean equals();

+

boolean equals(Object x);


/** Hash function depends only on the equality of corresponding members. */


/** Hash function depends only on the equality of corresponding members. */


int hashCode().


int hashCode().

Line 318:

Line 328:


The JVM provides an instance of <code>StaticContext</code> when it performs up-calls. The representation of this object is completely implementation dependent. The object must not be mutable.


The JVM provides an instance of <code>StaticContext</code> when it performs up-calls. The representation of this object is completely implementation dependent. The object must not be mutable.





-

Several call sites can share a single <code>StaticContext</code>, if they refer to similar instructions in the same caller class. No two calls in the bytecodes may have the same <code>CallSite</code> object.

+

Static context objects with identical properties (caller class, name, type) are always interchangeable; object identity is insignificant. By contrast, call site objects (described in more detail below) are distinguished by object identity.

-

 

+


-

The JVM is permitted to split invocation sites in the bytecode into multiple <code>CallSite</code> objects, each with a distinct <code>StaticContext</code>. This might happen, for example, if the JVM internally inlines methods which contain <code>invokedynamic</code> instructions.

+






-

(<em>Note:</em> For the UID, a JVM implementation could use the invocation&rsquo; BCI (bytecode index within the method) and a low-level index to distinguish the calling method, if method inlining does not lead to call site splitting.)

+

(<em>Note:</em> There is no need to specify a bytecode index in a call site&rsquo;s static context. Such a number would not be very useful, even if the dynamic language backend built some sort of BCI-based table, because low-level bytecode editing could change bytecode indexes independently of the backend. If individual call sites must be distinguished, and if the call site objects themselves are unsuitable as map keys, the language backend can create extra back-channels by embedding data in the method name string, or in hidden arguments.)






(<em>Note:</em> An alternative to the <code>StaticContext</code> argument would be a &#8220;magic&#8221; method which walks up the stack, like <code>Reflection.getCallerClass</code> or <code>Thread.getStackTrace</code>. This does not provide a &#8220;hook&#8221; for distinguishing call sites, however.)


(<em>Note:</em> An alternative to the <code>StaticContext</code> argument would be a &#8220;magic&#8221; method which walks up the stack, like <code>Reflection.getCallerClass</code> or <code>Thread.getStackTrace</code>. This does not provide a &#8220;hook&#8221; for distinguishing call sites, however.)

Line 361:

Line 369:


If the caller class is not registering on its own behalf, a security manager check is made. See below.


If the caller class is not registering on its own behalf, a security manager check is made. See below.





-

(<em>Note:</em> If the language-specific loader needs to associate a non-constant &#8220;language runtime&#8221; object with the loaded class, it can link this object from the <code>ClassLoader</code> used to install the class. The bootstrap method can access this runtime object via <code>StaticContext.getCallerClass</code>.)

+

(<em>Note:</em> If the language-specific loader needs to associate a non-constant &#8220;language runtime&#8221; object with the loaded class, it can link this object from the <code>ClassLoader</code> used to install the class. The bootstrap method can access this runtime object via <code>StaticContext.callerClass</code>.)






== Target method processing ==


== Target method processing ==

Line 380:

Line 388:


=== Call site contents ===


=== Call site contents ===





-

A <code>CallSite</code> object provides access to the linkage state of a call, and also gives a few details about the testing of the arguments.

+

A <code>CallSite</code> object provides access to the linkage state of a call, and also reveals that static context of the call.






The API looks like this:


The API looks like this:

Line 389:

Line 397:


public MethodHandle getTarget();


public MethodHandle getTarget();


public void setTarget(MethodHandle target);


public void setTarget(MethodHandle target);

-

public StaticContext getStaticContext();

+

public StaticContext staticContext();


}


}


</pre>


</pre>

 

+


 

+

The linkage state corresponding to a single <code>CallSite</code> object is always a single reference. This reference may be updated from any thread, as if it were an ordinary variable in the Java heap.

 

+


 

+

(<em>Note:</em> The linkage state is not guaranteed to have volatile semantics, which means there may be a delay between a change in one thread and an effect in another. The bulk invalidation API supplies a more expensive but more rigidly sequenced update of this variable.)

 

+


 

+

Several call sites can share a single <code>StaticContext</code>, if they refer to similar instructions in the same caller class. No two calls in the bytecodes may have the same <code>CallSite</code> object.

 

+


 

+

Call site identity is significant. No two distinct call sites may refer to the same linkage state.

 

+


 

+

The JVM is permitted to split invocation sites in the bytecode into multiple <code>CallSite</code> objects, each with a distinct identity and linkage state. This might happen, for example, if the JVM internally inlines methods which contain <code>invokedynamic</code> instructions. Whenever it does so, the JVM must also present distinct <code>CallSite</code> objects (to the bootstrap method) to correspond to the distinct linkage states.

 

+


 

+

If a bulk invalidation invalidates a call site, the JVM is allowed (but not required) to create a new <code>CallSite</code> object to represent the linkage state of a call site that has been reset.

 

+


 

+

=== Call site data flow ===






The receiver of the <code>invokedynamic</code> instruction is treated like any stacked argument, and may or may not end up as the receiver of an eventual method being called.


The receiver of the <code>invokedynamic</code> instruction is treated like any stacked argument, and may or may not end up as the receiver of an eventual method being called.

Line 421:

Line 443:






(<em>Issue:</em> Is this too much of a push interface? Experiment will tell.)


(<em>Issue:</em> Is this too much of a push interface? Experiment will tell.)

 

+


 

+

(<em>Issue:</em> Should there be an <code>invalidateContext</code> which takes a <code>StaticContext</code> argument? If so, should the argument context be allowed to present wildcards, such as null values, for its caller class, name, and type?)






(<em>Issue:</em> Is there some other, better system of predicates to describe call sites?)


(<em>Issue:</em> Is there some other, better system of predicates to describe call sites?)

Line 443:

Line 467:






== Change log ==


== Change log ==

-

* 1.0 first EDR draft

+

* 1.01 EDR (Jume 2008)

 

+

** regularize accessor names (use get/set only for changeable state)

 

+

** clarify significance of object identity for call sites and static context

 

+

** add more rationale about various data types

 

+

** discuss non-use of bytecode indexes in static contexts

 

+

** clarify treatment of unloaded classes in method type components

 

+

** clarify non-volatile update semantics of linkage state

 

+

** acknowledgements: Remi Forax, Rich Hickey, Jevgeni Kabanov, http://groups.google.com/group/jvm-languages

 

+

* 1.0 first EDR draft (19 May 2008)


** remove JVM-managed target method cache


** remove JVM-managed target method cache


** make the linkage state be a single target method handle


** make the linkage state be a single target method handle