Thanks for the review, Sundar.

I think making thresholds configurable is a good idea. I’ve uploaded a new 
webrev where SHARED_CALL_THRESHOLD and SHARED_GET_THRESHOLD are configurable 
via „nashorn.shared.scope.call.threshold“ and 
„nashorn.shared.scope.get.threshold“ system properties, respectively. 

http://cr.openjdk.java.net/~hannesw/8069338/webrev.02/

Hannes

> Am 12.12.2017 um 14:00 schrieb Sundararajan Athijegannathan 
> <sundararajan.athijegannat...@oracle.com>:
> 
> +1
> 
> PS. Not sure if it is worth making SHARED_GET_THRESHOLD configurable via 
> System property?
> 
> -Sundar
> 
> On 12/12/17, 5:51 PM, Hannes Wallnöfer wrote:
>> Thanks for the review, Attila.
>> 
>> I’ve uploaded a new webrev with your suggested changes (including making 
>> ScriptObject.getProto(int) accept 0 argument and refactoring GET_PROTO code 
>> in CodeGenerator into a method).
>> 
>> I have also done extensive performance testing over the last days and found 
>> that for some reason, shared methods for variable access has a very 
>> detrimental effect on performance for some reason. My theory is that we 
>> don’t save as much by making property access shared, and the flood of 
>> additional methods has some significant cost on codegen, runtime, JIT etc. 
>> Based on this I decided to increase the threshold for shared property access 
>> again to 100, which performs noticeably better than with the lower threshold 
>> in some benchmarks.
>> 
>> New webrev is here:
>> 
>> http://cr.openjdk.java.net/~hannesw/8069338/webrev.01/
>> 
>> Hannes
>> 
>> 
>>> Am 11.12.2017 um 11:55 schrieb Attila Szegedi<szege...@gmail.com>:
>>> 
>>> Reviewing this now, thanks for going ahead and implementing it!
>>> 
>>> So what you are saying about slow scopes is that shared scopes were 
>>> disabled anyway with them for some time, so you didn’t really take away 
>>> functionality, just cleaned up the remains?
>>> 
>>> So, some remarks:
>>> 
>>> 1. I see the bytecode shape you wrote around invocation of 
>>> ScriptObject.getProto(int), and I realized it’s weird it asserts n>  0 and 
>>> it has the first getProto() unrolled before the loop. I’m pretty sure it 
>>> can just look like this:
>>> 
>>> public final ScriptObject getProto(final int n) {
>>>     ScriptObject p = this;
>>>     for (int i = n; i-->  0;) {
>>>         p = p.getProto();
>>>     }
>>>     return p;
>>> }
>>> 
>>> That assert was there because we knew that it’s only CodeGenerator that 
>>> emits calls to it, and it will always emit invocations with n>  0, but now 
>>> we’d have a justification for invoking it with n == 0, so I think it’s fine 
>>> to do it and avoid the no_proto_call branch in shared scope call bytecode. 
>>> It’s not a big deal even if you leave it as-is, though.
>>> 
>>> To be entirely pedantic, that assert in getProto should’ve read “n>  1” 
>>> before because the CodeGenerator was guaranteed to emit invocations to it 
>>> with n>  1, so a really pedantic implementation of it should’ve read:
>>> 
>>> public final ScriptObject getProto(final int n) {
>>>     assert n>  1;
>>>     ScriptObject p = getProto().getProto();
>>>     for (int i = n - 1; --i>  0;) {
>>>         p = p.getProto();
>>>     }
>>>     return p;
>>> }
>>> 
>>> (God, I really hope everyone reading this realizes I’m joking with this 
>>> last one.)
>>> 
>>> FWIW, we could also factor out the:
>>> 
>>> if (depth>  1) {
>>>     method.load(depth);
>>>     method.invoke(ScriptObject.GET_PROTO_DEPTH);
>>> } else {
>>>     method.invoke(ScriptObject.GET_PROTO);
>>> }
>>> 
>>> pattern in CodeGenerator into its own little “emitGetProto(int depth)” 
>>> method, as it appears twice (and make sure it asserts on depth>  0 ;-) )
>>> 
>>> 2. For that invocation of UnwarrantedOptimismException.withProgramPoint - 
>>> I’d create a Call objects using CompilerConstants.virtualCallNoLookup and 
>>> stash it in a static final field either in SharedScopeCall or 
>>> UnwarrantedOptimismException; it’s more typesafe than writing type 
>>> descriptors as strings.
>>> 
>>> 3. So, UOE.hasPrimitiveReturnValue was unused, I take it?
>>> 
>>> 3. In getStaticSignature you have another occurrence of number 3 that you 
>>> can replace with FIXED_PARAM_COUNT :-)
>>> 
>>> But these are all minor points… overall, this looks really good.
>>> 
>>> Attila.
>>> 
>>>> On Dec 6, 2017, at 6:43 PM, Hannes Wallnöfer<hannes.wallnoe...@oracle.com> 
>>>>  wrote:
>>>> 
>>>> Please review:
>>>> 
>>>> Bug: https://bugs.openjdk.java.net/browse/JDK-8069338
>>>> Webrev: http://cr.openjdk.java.net/~hannesw/8069338/webrev.00/
>>>> 
>>>> This implements shared scope calls for optimistic vars/calls. I followed 
>>>> Attila’s blueprint in the bug description to the last detail - thanks for 
>>>> figuring it all out.
>>>> 
>>>> Some adjustments and cleanups I did along the way:
>>>> 
>>>> - Originally shared scope calls were designed to support slow scope vars 
>>>> (with/eval). However, that feature was disabled later on. I refactored the 
>>>> code to make it clear that we only do shared scope calls for fast scope 
>>>> operations.
>>>> - I unified the threshold for all shared scope operations to 5. I don’t 
>>>> think there is a reason for different thresholds for different operations. 
>>>> I did some testing, using 5 as threshold appeared to be a sensible value.
>>>> 
>>>> Running all of the  octane benchmark I see a decrease in created callsites 
>>>> (200 000 to 178 000) and a slight decrease in callsite invalidations.
>>>> 
>>>> Hannes

Reply via email to