Isolated Methods JEP

John Rose john.r.rose at oracle.com
Fri Aug 12 23:48:41 UTC 2016


On Aug 12, 2016, at 2:56 PM, Michael Haupt <michael.haupt at oracle.com> wrote:
> 
> Hi Mark,
> 
>> Am 05.08.2016 um 12:13 schrieb Mark Roos <mroos at roos.com <mailto:mroos at roos.com>>:
>> Good to see this.
> 
> thanks. :-)
> 
>> What is the philosophy for code annotations, line numbers and stack maps? 
>> 
>> Would they be some form of constant entry? 
> 
> I recall you had asked this question at JVMLS. I think it definitely makes sense to add support for these. How would you think they should be represented?
> 
> Here are some thoughts.
> 
> First, stack maps. Leave their generation to the bytecode generation framework responsible for producing the bytecode array (whichever one that may be), allow for easy extraction of the map from its generation result, and for passing that on to the loadCode implementation. This will require a library-level representation of stack maps (inspired by Sec. 4.7.4 of the JVM Spec), unless the plain class file format for them is used - which may not be desirable given the convenience attempts the API is making with the constants array. To maintain convenience, stack map generation could be the responsibility of the loadCode implementation. This would duplicate the work of generating the map, which seems rather unwelcome.

I think the right answer will involve making the verification of IM bytecodes simpler.  For example, if there is no invokespecial, all the nasty rules for that instruction go away (along with those for "new").  Frame maps are designed to support one-pass checking of bytecodes.  There are restrictions we can put on IM bytecodes that will recover the ability to perform one-pass checking, with implicitly derived frame maps.  In a nutshell, the first type-state wins, and any other type-states (e.g., from backward branches) need to match.  This makes it very slightly harder to generate IM bytecodes (with sometimes an extra checkcast for merge points), but in exchange nobody needs to mess with frame maps (except maybe VM internals).

This does lead me to an extra thought:  I think IM's could be given the capability to have multiple entry points.  This would allow a number of interesting applications, starting with exception handling that appeals to a helper object, instead of a handler table and some special verifier rules.

Immediately beyond that, although now I'm being a Mission Creep, if an IM has multiple entry points for exception handling, it could also use these entry points for frame resumption, as described by Ron Pressler in a previous JVMLS, and Andrey Breslav this year.  (That leads to the question of how an IM can yield to an suspension point, a very good question.  And something that a helper object can help with.  And so on.  This might help us do fibers experiments more quickly.)

> Annotations can be passed as a map from annotation classes to lists of values. Line numbers can be passed as an int array of pairs of numbers, where even indices represent start PCs, and odd indices, line numbers.

> Adding to your list, a source file association can be represented as a URL or String. (Cream on top: a multiline String containing the IM's actual source code.)

I hope all that logic can be wrapped up in a helper object, to be executed only when needed.  I.e., load quickly *with no paperwork*, and have the helper object figure out what happened later on, if we get asked.

interface IsolatedMethod { // reflected view of raw IM
  // recovered arguments to Lookup.loadCode:
  Lookup lookup();
  String name();
  MethodType type();
  ByteSequence bytes();  // NOTE: R/O view; same type for CONSTANT_Bytes
  List<Object> constants();

  // this has to be stuck in somehow:
  //Inspector inspector();

  interface Inspector {  // helper for "paperwork"
    String sourceFile(IsolatedMethod m);
    String className(IsolatedMethod m);
    int mapLineNumber(IsolatedMethod m, int bci);
    List<LocalVariableInfo> mapLocalVariables(IsolatedMethod m, int bci);
    List<HandlerInfo> mapExceptionHandlers(IsolatedMethod m, int bci);
    List<Class> mapFrameState(IsolatedMethod m, int bci);
    ...
    //?MethodHandleInfo methodHandleInfo(IsolatedMethod m);
  }
}

> As a further addition, exceptions can be passed as a simple array or list, and an exception handler table can be passed as a tuple (not in the Valhalla sense, yet) of an int array of triplets of numbers representing start, end, and handler PCs and of a list or array of exception classes.

Yes, exception handling is the tricky part (along with verification).  Maybe we could use an Inspector to help extract the details:

interface Inspector { …
  int exceptionContinuationPoint(IsolatedMethod m, int bci, Class<? extends Throwable> exc);
}

The idea would be to call the IM inspector for a continuation point.  Of course, that thing might throw an exception, which makes the model muddy, though not impossible.  Verification of the CP could be lazy, or the CP's could be marked up front and checked during loadCode.

There's a fiber frame system struggling to emerge here.

— John
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/mlvm-dev/attachments/20160812/1757b830/attachment.html>


More information about the mlvm-dev mailing list