Modifying graph to include InvokeNode

Christian Thalinger christian.thalinger at oracle.com
Tue Jul 16 11:00:14 PDT 2013


On Jul 16, 2013, at 10:39 AM, Doug Simon <doug.simon at oracle.com> wrote:

> As much as C2? If so, that's a pleasant surprise (to me at least).

Yeah, I pushed the change some time ago based on the work from… sorry, I forgot his name.  Perhaps a Christian ;-)

Performance was a bit behind compared to C2, though.  Christian Haeubl did some inlining work but I think we are not there yet.

-- Chris

> 
> Sent from my iPhone
> 
> On Jul 16, 2013, at 7:31 PM, Thomas Wuerthinger <thomas.wuerthinger at oracle.com> wrote:
> 
>> Actually Graal fully supports and optimizes invokedynamic and JSR292 code.
>> 
>> - thomas
>> 
>> On Jul 16, 2013, at 9:03 AM, Doug Simon <doug.simon at oracle.com> wrote:
>> 
>>> 
>>> On Jul 16, 2013, at 5:33 PM, Remi Forax <forax at univ-mlv.fr> wrote:
>>> 
>>>> On 07/16/2013 05:27 PM, Doug Simon wrote:
>>>>> On Jul 16, 2013, at 4:41 PM, Christophe Dubach <christophe.dubach at ed.ac.uk> wrote:
>>>>> 
>>>>>> Dear Doug,
>>>>>> 
>>>>>> I'm currently supervising Chris with his work and have been following the discussion.
>>>>>> 
>>>>>> I am quite surprised that it is not possible to add an InvokeNode in a the graph of a method at runtime. When you say "We can only add static calls that are guaranteed to never be deoptimized" do you mean the callee or the caller? I am probably ignorant but I don't see what would be the difference between inserting an invokeNode to static method (not created dynamically) and an IntergerAdd node in the graph at runtime.
>>>>> An invoke node (that doesn't get inlined) in method A that calls method B will result in a call in the generated code. During execution of B, something may happen to invalidate an assumption made when compiling A (e.g., class loading invalidating a class hierarchy speculation). This means A is now invalid and needs to be deoptimized upon return from B. In the current system, we rely on HotSpot's deoptimization infrastructure to continue execution at the return site of A in the interpreter. HotSpot only (currently) supports deoptimize-on-return for call sites that have the BCI of an invoke bytecode.
>>>>> 
>>>>> One could modify HotSpot to have more general deoptimization support or we could modify Graal to handle invokes inserted for instrumentation. However, both of these tasks are non-trivial. Since our current focus is not on making Graal an all purpose instrumentation framework, we probably won't invest much effort in them in the near future.
>>>>> 
>>>>>> Anyway, thanks for the suggestion of doing bytecode instrumentation. Is it possible to do this directly with Graal or where you talking about patching the method at class load time?
>>>>> The latter. Although you could use Graal in conjunction with a bytecode instrumentation library such as ASM for building a graph from the bytecode and finding the loops.
>>>>> 
>>>>>> In our scenario, we want to limit our instrumentation to hot methods in order to further optimise them, therefore, we were aiming to do all this in the jit compiler.
>>>>> What you really want is a Java interpreter based on Truffle[1][2]. We have gone someway down this path ourselves but don't yet have anything publicly available.
>>>> 
>>>> The other solution is to use invokedynamic, if Graal support it ?
>>> 
>>> It supports it but does not (yet) optimize it.
>>> 
>>> -Doug
>>> 
>>>> 
>>>>>> Thanks,
>>>>>> Christophe.
>>>>>> 
>>>>>> 
>>>>>> On 16/07/13 14:43, Doug Simon wrote:
>>>>>>> On Jul 16, 2013, at 3:27 PM, ATKIN-GRANVILLE Chris <s1255753 at sms.ed.ac.uk> wrote:
>>>>>>> 
>>>>>>>> Oh, that may have been a silly thing to say, I know you can't "get" the BCI of a method call that doesn't exist in the bytecode. Even still, it seems like quite a large omission from graal to not be able to add static method calls into a graph…
>>>>>>> We can only add static calls that are guaranteed to never be deoptimized since there is no valid interpreter state to continue in for such invocations. I doubt that any bytecode compiler that relies on deoptimization could do any different…
>>>>>>> 
>>>>>>> For your use case, bytecode instrumentation is what you want. Especially since you (seem to) need complete dynamic coverage of the code patterns you are interested in instrumenting.
>>>>>>> 
>>>>>>> -Doug
>>>>>>> 
>>>>>>>> On 16 Jul 2013, at 14:19, ATKIN-GRANVILLE Chris <s1255753 at sms.ed.ac.uk>
>>>>>>>> wrote:
>>>>>>>> 
>>>>>>>>> Is it not possible to somehow "get" that BCI? It doesn't seem like adding static method calls should be impossible when graph transformations are possible...
>>>>>>>>> 
>>>>>>>>> On 16 Jul 2013, at 14:14, Doug Simon <doug.simon at oracle.com>
>>>>>>>>> wrote:
>>>>>>>>> 
>>>>>>>>>> This is almost certainly due to the fact that an invoke node must be associated with the BCI of a real invoke bytecode instruction. Otherwise, where would the interpreter resume if there is a deoptimization  during the invocation?
>>>>>>>>>> 
>>>>>>>>>> On Jul 16, 2013, at 2:22 PM, ATKIN-GRANVILLE Chris <s1255753 at sms.ed.ac.uk> wrote:
>>>>>>>>>> 
>>>>>>>>>>> Hi there,
>>>>>>>>>>> 
>>>>>>>>>>> I'm trying to modify the graph to include an invoke node to a static function after certain node types. I'm modifying the graph at a high level before LoweringPhase.class (not a requirement, can change if required). However, I'm running into issues with JVM fatal errors. The code I have at the moment looks like this:
>>>>>>>>>>> 
>>>>>>>>>>> public class MyPhase extends Phase {
>>>>>>>>>>>   public void run(StructuredGraph graph) {
>>>>>>>>>>>       for (Node node: graph.getNode()) {
>>>>>>>>>>> 
>>>>>>>>>>>           if ( node instanceof RandomFixedNode) {
>>>>>>>>>>>               RandomFixedNode rfm = (RandomFixedNode) node;
>>>>>>>>>>> 
>>>>>>>>>>>               try {
>>>>>>>>>>>                   ResolvedJavaMethod method = getMethod(…);
>>>>>>>>>>>                   MethodCallTargetMode callTarget = graph.add(new MethodCallTargetNode(MethodCallTargetNode.InvokeKind.Static,
>>>>>>>>>>>                       method, new ValueNode[] {}, new HotSpotResolvedPrimitiveType(Kind.Void)));
>>>>>>>>>>> 
>>>>>>>>>>>                   InvokeNode invoke = graph.add(new InvokeNode(callTarget, FrameState.UNKNOWN_BCI));
>>>>>>>>>>>                   invoke.setStateAfter(graph.add(new FrameState(FrameState.UNKNOWN_BCI)));
>>>>>>>>>>>                   graph.addAfterFixed(rfm, invoke);
>>>>>>>>>>> 
>>>>>>>>>>>               } catch (Exception e) {
>>>>>>>>>>>                   e.printStackTrace();
>>>>>>>>>>>               }
>>>>>>>>>>>           }
>>>>>>>>>>> 
>>>>>>>>>>>       }
>>>>>>>>>>>   }
>>>>>>>>>>> }
>>>>>>>>>>> 
>>>>>>>>>>> I'm pretty sure the problem is do with the BCIs and/or the FrameStates, but I don't know how to fix it. The error that I get is:
>>>>>>>>>>> 
>>>>>>>>>>> Internal Error (/Volumes/Acme/Development/graal/src/share/vm/graal/graalCompilerToVM.cpp:44), pid=8466, tid=5379
>>>>>>>>>>> assert(hotspot_method != NULL && hotspot_method->is_a(HotSpotResolvedJavaMethod::klass())) failed: sanity
>>>>>>>>>>> 
>>>>>>>>>>> Does anyone have any ideas?
>>>>>>>>>>> 
>>>>>>>>>>> Thanks, Chris
>>>>>>>>>>> 
>>>>>>>>>>> -- 
>>>>>>>>>>> The University of Edinburgh is a charitable body, registered in
>>>>>>>>>>> Scotland, with registration number SC005336.
>>>>>>>>> 
>>>>>>>>> -- 
>>>>>>>>> The University of Edinburgh is a charitable body, registered in
>>>>>>>>> Scotland, with registration number SC005336.
>>>>>>>> 
>>>>>>>> -- 
>>>>>>>> The University of Edinburgh is a charitable body, registered in
>>>>>>>> Scotland, with registration number SC005336.
>>>>>> 
>>>>>> -- 
>>>>>> The University of Edinburgh is a charitable body, registered in
>>>>>> Scotland, with registration number SC005336.
>> 



More information about the graal-dev mailing list