JDK-8056052 : jdk.nashorn.internal.runtime.Source.getContent() does excess Object.clone()
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: jdk.nashorn
  • Affected Version: 8u40
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2014-08-26
  • Updated: 2015-06-04
  • Resolved: 2014-08-26
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
8u40Fixed 9 b29Fixed
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 220 seconds of run, ~5 seconds are spent here:

6.160	jdk.nashorn.internal.parser.Parser.parse()
6.160	jdk.nashorn.internal.parser.Parser.parse(java.lang.String, int, int, boolean)
4.830	jdk.nashorn.internal.parser.Lexer.<init>(jdk.nashorn.internal.runtime.Source, int, int, jdk.nashorn.internal.parser.TokenStream, boolean)
4.830	jdk.nashorn.internal.runtime.Source.getContent()
4.820	java.lang.Object.clone()

Sundar tells me that defensive copy is needed to shut FindBugs up, which means we could gain the performance back by sharing the original char[] via getContent()
Either way is fine, but just dropping ".clone()" helps already. "JavaScript Parsing" is faster from 14(+-)1 sec to 11(+-)1 sec on a single-iteration compile-octane.js. Single-iteration tests are more susceptible since C2 is unable to inline Object.clone() there just yet.

Alternatively, we could have Lexer work with a CharSequence instead of char[] and have Source.getContent return either a CharSequence, or itself be a CharSequence.