JDK-8055909 : Reflective set of SOURCE/CONSTANTS is hot in jdk.nashorn.internal.runtime.Context$ContextCodeInstaller
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: jdk.nashorn
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: generic
  • CPU: generic
  • Submitted: 2014-08-25
  • Updated: 2014-08-26
  • Resolved: 2014-08-26
Related Reports
Relates :  
Relates :  
Profiling a simple scenario: 

$ ~/Install/jdk9u20/bin/java -jar dist/nashorn.jar -Dnashorn.typeInfo.disabled=false --class-cache-size=0 --persistent-code-cache=false -scripting --log=time test/script/basic/compile-octane.js -- --iterations 5 

...yields a few simple low-hanging fruits, here is one of them. Out of 320 seconds of run, and 38 seconds spent in class installation time, ~13 seconds are spent here: 

12.690	jdk.nashorn.internal.codegen.CompilationPhase$12.transform(jdk.nashorn.internal.codegen.Compiler, jdk.nashorn.internal.codegen.Compiler$CompilationPhases, jdk.nashorn.internal.ir.FunctionNode)
5.220	jdk.nashorn.internal.runtime.Context$ContextCodeInstaller.initialize(java.util.Collection, jdk.nashorn.internal.runtime.Source, java.lang.Object[])
5.170	jdk.nashorn.internal.runtime.Context$ContextCodeInstaller$1.accept(java.lang.Class)
5.170	java.security.AccessController.doPrivileged(java.security.PrivilegedExceptionAction)
5.120	jdk.nashorn.internal.runtime.Context$ContextCodeInstaller$1$1.run()
5.000	java.lang.Class.getDeclaredField(java.lang.String)
4.940	java.lang.Class.privateGetDeclaredFields(boolean)
4.920	java.lang.Class.getDeclaredFields0(boolean)
4.890	JVM_GetClassDeclaredFields
4.610	InstanceKlass::link_class(Thread*)
4.770	InstanceKlass::link_class_impl(instanceKlassHandle,bool,Thread*)
3.700	Verifier::verify(instanceKlassHandle,Verifier::Mode,bool,Thread*)
3.630	ClassVerifier::verify_method(methodHandle,Thread*)

Update: See updated stack trace, it seems like the first call to getDeclaredFields causes the class to initialize and link. We spend the largest slob of time verifying the incoming bytecode.
Optimizing Reflection parts in Nashorn is obvious WNF.

Yes, in JDK-8053904, we confirmed the Verifier is a real bottleneck.

That would not work, see the updated description: we indeed spend most of the time linking the class, and there we spend most of the time verifying its bytecode. Given that we will allegedly link the class later, the only thing left for us is asking for a faster bytecode verifier.

one way to avoid reflection and do it during class construction is to put these values in a thread local, and emit a <clinit> that populates the fields from the thread local. That will enlarge every class with one <clinit> worth of bytecode - that's the tradeoff.

I understand the part about initializing the class sooner or later, but maybe "later" never happens down the way, if we fix "sooner" here.

Is there any way to inject SOURCE and CONSTANTS as proper constants during the class construction, and avoid Reflection at all?

I think what happens here is that the first call to getDeclaredFields will force the class to be resolved, so the bulk of its time cost is actually a hidden cost of class resolving, which'll need to happen sooner or later anyway. (I might be wrong here, but I seem to recall this was the case.)