2012-12-21 20:36:24 +00:00
|
|
|
This document describes system properties that are used for internal
|
|
|
|
debugging and instrumentation purposes, along with the system loggers,
|
|
|
|
which are used for the same thing.
|
|
|
|
|
|
|
|
This document is intended as a developer resource, and it is not
|
|
|
|
needed as Nashorn documentation for normal usage. Flags and system
|
|
|
|
properties described herein are subject to change without notice.
|
|
|
|
|
|
|
|
=====================================
|
|
|
|
1. System properties used internally
|
|
|
|
=====================================
|
|
|
|
|
|
|
|
This documentation of the system property flags assume that the
|
|
|
|
default value of the flag is false, unless otherwise specified.
|
|
|
|
|
2013-03-26 07:42:35 +00:00
|
|
|
SYSTEM PROPERTY: -Dnashorn.args=<string>
|
|
|
|
|
|
|
|
This property takes as its value a space separated list of Nashorn
|
2013-08-23 13:46:09 +00:00
|
|
|
command line options that should be passed to Nashorn. This might be
|
|
|
|
useful in environments where it is hard to tell how a nashorn.jar is
|
|
|
|
launched.
|
2013-03-26 07:42:35 +00:00
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
> java -Dnashorn.args="--lazy-complation --log=compiler" large-java-app-with-nashorn.jar
|
|
|
|
> ant -Dnashorn.args="--log=codegen" antjob
|
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
SYSTEM PROPERTY: -Dnashorn.args.prepend=<string>
|
|
|
|
|
|
|
|
This property behaves like nashorn.args, but adds the given arguments
|
|
|
|
before the existing ones instead of after them. Later arguments will
|
|
|
|
overwrite earlier ones, so this is useful for setting default arguments
|
|
|
|
that can be overwritten.
|
|
|
|
|
|
|
|
|
2013-01-07 18:31:36 +00:00
|
|
|
SYSTEM PROPERTY: -Dnashorn.unstable.relink.threshold=x
|
|
|
|
|
2015-11-09 14:37:07 +00:00
|
|
|
NOTE: This property is deprecated in favor of the
|
|
|
|
"--unstable-relink-threshold" command line option. It controls how many
|
|
|
|
call site misses are allowed before a callsite is relinked with "apply"
|
|
|
|
semantics to never change again. In the case of megamorphic callsites,
|
|
|
|
this is necessary, or the program would spend all its time swapping out
|
|
|
|
callsite targets. When neither the system property nor the command line
|
|
|
|
option are specified, defaults to 8, or 16 with optimistic types turned
|
|
|
|
on.
|
2013-01-07 18:31:36 +00:00
|
|
|
|
2012-12-21 20:36:24 +00:00
|
|
|
|
2013-02-12 12:55:05 +00:00
|
|
|
SYSTEM PROPERTY: -Dnashorn.compiler.splitter.threshold=x
|
2013-01-11 09:40:51 +00:00
|
|
|
|
|
|
|
This will change the node weight that requires a subgraph of the IR to
|
|
|
|
be split into several classes in order not to run out of bytecode space.
|
|
|
|
The default value is 0x8000 (32768).
|
|
|
|
|
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
SYSTEM PROPERTY: -Dnashorn.serialize.compression=<x>
|
2012-12-21 20:36:24 +00:00
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
This property sets the compression level used when deflating serialized
|
|
|
|
AST structures of anonymous split functions. Valid values range from 0 to 9,
|
|
|
|
the default value is 4. Higher values will reduce memory size of serialized
|
|
|
|
AST but increase CPU usage required for compression.
|
2012-12-21 20:36:24 +00:00
|
|
|
|
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
SYSTEM PROPERTY: -Dnashorn.codegen.debug.trace=<x>
|
2012-12-21 20:36:24 +00:00
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
See the description of the codegen logger below.
|
2012-12-21 20:36:24 +00:00
|
|
|
|
|
|
|
|
2015-04-10 12:18:31 +00:00
|
|
|
SYSTEM PROPERTY: -Dnashorn.fields.objects, -Dnashorn.fields.dual
|
|
|
|
|
|
|
|
When the nashorn.fields.objects property is true, Nashorn will always
|
|
|
|
use object fields for AccessorProperties, requiring boxing for all
|
|
|
|
primitive property values. When nashorn.fields.dual is set, Nashorn
|
|
|
|
will always use dual long/object fields, which allows primitives to be
|
|
|
|
stored without boxing. When neither system property is set, Nashorn
|
|
|
|
chooses a setting depending on the optimistic types setting (dual
|
|
|
|
fields when optimistic types are enabled, object-only fields otherwise).
|
|
|
|
|
|
|
|
With dual fields, Nashorn uses long fields to store primitive values.
|
|
|
|
Ints are represented as the 32 low bits of the long fields. Doubles
|
|
|
|
are represented as the doubleToLongBits of their value. This way a
|
2014-10-23 15:25:39 +00:00
|
|
|
single field can be used for all primitive types. Packing and
|
|
|
|
unpacking doubles to their bit representation is intrinsified by
|
|
|
|
the JVM and extremely fast.
|
2012-12-21 20:36:24 +00:00
|
|
|
|
|
|
|
In the future, this might complement or be replaced by experimental
|
|
|
|
feature sun.misc.TaggedArray, which has been discussed on the mlvm
|
|
|
|
mailing list. TaggedArrays are basically a way to share data space
|
|
|
|
between primitives and references, and have the GC understand this.
|
|
|
|
|
|
|
|
|
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes
Lower suffered from being a "God class" trying to do everything at once. As Nashorn code generation has grown, so has Lower. It does several post processing passes, tries to do several things at once even though all type information isn't in place, adjusting state afterwards and so on. It also performs control flow analysis, type attribution and constant folding, and everything else code generation related before byte code emission. I have now separated the compilation process into Lower (create low level nodes from high level ones, copy code such as finally block inlining etc), Attr (assign types and symbols to all nodes - freeze slot and scope information) and FinalizeTypes (insert explicit casts, specialize invoke dynamic types for scope accesses). I've removed the kludgy AccessSpecializer, as this now integrates naturally with typing. Everything is now much easier to read and each module performs only one thing. I have added separate loggers for the separate tiers. In the process I have also fixed: (1) problems with type coercion (see test/script/basic/typecoercion.js, basically our coercion was too late and our symbol inference was erroneous. This only manifested itself in very rare occasions where toNumber coercion has side effects, such as for example when valueOf is overridden) (2) copying literal nodes (literal copy did not use the superclass copy, which made all the Node specific fields not to be copied (3) erroneous literal tokenization (literals shouldn't always just inherit token information from whatever node that creates them) (4) splitter weighnodes - unary nodes were considered weightless (4) removed the hateful and kludgy "VarNode.shouldAppend", which really isn't needed when we have an attribution phase that determines self reference symbols (the only thing it was used for) (5) duplicate line number issues in the parser (6) convert bug in CodeGenerator for intermediate results of scope accesses (see test/script/basic/access-specializer.js) ... Several of these things just stopped being problems with the new architecture "can't happen anymore" and are not bug fixes per se. All tests run. No performance regressions exist that I've been able to measure. Some increases in performance were measured, but in the statistical margin of error (which is very wide as HotSpot currently has warmup issues with LambdaForms/invoke dynamic). Compile speed has not measurably increased.
Reviewed-by: jlaskey, attila
2013-01-30 11:26:45 +00:00
|
|
|
SYSTEM PROPERTY: -Dnashorn.compiler.symbol.trace=[<x>[,*]],
|
|
|
|
-Dnashorn.compiler.symbol.stacktrace=[<x>[,*]]
|
2012-12-21 20:36:24 +00:00
|
|
|
|
|
|
|
When this property is set, creation and manipulation of any symbol
|
|
|
|
named "x" will show information about when the compiler changes its
|
|
|
|
type assumption, bytecode local variable slot assignment and other
|
|
|
|
data. This is useful if, for example, a symbol shows up as an Object,
|
|
|
|
when you believe it should be a primitive. Usually there is an
|
|
|
|
explanation for this, for example that it exists in the global scope
|
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes
Lower suffered from being a "God class" trying to do everything at once. As Nashorn code generation has grown, so has Lower. It does several post processing passes, tries to do several things at once even though all type information isn't in place, adjusting state afterwards and so on. It also performs control flow analysis, type attribution and constant folding, and everything else code generation related before byte code emission. I have now separated the compilation process into Lower (create low level nodes from high level ones, copy code such as finally block inlining etc), Attr (assign types and symbols to all nodes - freeze slot and scope information) and FinalizeTypes (insert explicit casts, specialize invoke dynamic types for scope accesses). I've removed the kludgy AccessSpecializer, as this now integrates naturally with typing. Everything is now much easier to read and each module performs only one thing. I have added separate loggers for the separate tiers. In the process I have also fixed: (1) problems with type coercion (see test/script/basic/typecoercion.js, basically our coercion was too late and our symbol inference was erroneous. This only manifested itself in very rare occasions where toNumber coercion has side effects, such as for example when valueOf is overridden) (2) copying literal nodes (literal copy did not use the superclass copy, which made all the Node specific fields not to be copied (3) erroneous literal tokenization (literals shouldn't always just inherit token information from whatever node that creates them) (4) splitter weighnodes - unary nodes were considered weightless (4) removed the hateful and kludgy "VarNode.shouldAppend", which really isn't needed when we have an attribution phase that determines self reference symbols (the only thing it was used for) (5) duplicate line number issues in the parser (6) convert bug in CodeGenerator for intermediate results of scope accesses (see test/script/basic/access-specializer.js) ... Several of these things just stopped being problems with the new architecture "can't happen anymore" and are not bug fixes per se. All tests run. No performance regressions exist that I've been able to measure. Some increases in performance were measured, but in the statistical margin of error (which is very wide as HotSpot currently has warmup issues with LambdaForms/invoke dynamic). Compile speed has not measurably increased.
Reviewed-by: jlaskey, attila
2013-01-30 11:26:45 +00:00
|
|
|
and type analysis has to be more conservative.
|
|
|
|
|
|
|
|
Several symbols names to watch can be specified by comma separation.
|
|
|
|
|
|
|
|
If no variable name is specified (and no equals sign), all symbols
|
|
|
|
will be watched
|
|
|
|
|
|
|
|
By using "stacktrace" instead of or together with "trace", stack
|
|
|
|
traces will be displayed upon symbol changes according to the same
|
|
|
|
semantics.
|
2012-12-21 20:36:24 +00:00
|
|
|
|
|
|
|
|
2013-08-23 13:46:09 +00:00
|
|
|
SYSTEM PROPERTY: -Dnashorn.lexer.xmlliterals
|
2012-12-21 20:36:24 +00:00
|
|
|
|
|
|
|
If this property it set, it means that the Lexer should attempt to
|
|
|
|
parse XML literals, which would otherwise generate syntax
|
|
|
|
errors. Warning: there are currently no unit tests for this
|
|
|
|
functionality.
|
|
|
|
|
|
|
|
XML literals, when this is enabled, end up as standard LiteralNodes in
|
|
|
|
the IR.
|
|
|
|
|
|
|
|
|
2013-08-23 13:46:09 +00:00
|
|
|
SYSTEM_PROPERTY: -Dnashorn.debug
|
2012-12-21 20:36:24 +00:00
|
|
|
|
|
|
|
If this property is set to true, Nashorn runs in Debug mode. Debug
|
|
|
|
mode is slightly slower, as for example statistics counters are enabled
|
|
|
|
during the run. Debug mode makes available a NativeDebug instance
|
|
|
|
called "Debug" in the global space that can be used to print property
|
|
|
|
maps and layout for script objects, as well as a "dumpCounters" method
|
|
|
|
that will print the current values of the previously mentioned stats
|
|
|
|
counters.
|
|
|
|
|
|
|
|
These functions currently exists for Debug:
|
|
|
|
|
|
|
|
"map" - print(Debug.map(x)) will dump the PropertyMap for object x to
|
|
|
|
stdout (currently there also exist functions called "embedX", where X
|
|
|
|
is a value from 0 to 3, that will dump the contents of the embed pool
|
|
|
|
for the first spill properties in any script object and "spill", that
|
|
|
|
will dump the contents of the growing spill pool of spill properties
|
|
|
|
in any script object. This is of course subject to change without
|
|
|
|
notice, should we change the script object layout.
|
|
|
|
|
|
|
|
"methodHandle" - this method returns the method handle that is used
|
|
|
|
for invoking a particular script function.
|
|
|
|
|
|
|
|
"identical" - this method compares two script objects for reference
|
|
|
|
equality. It is a == Java comparison
|
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
"equals" - Returns true if two objects are either referentially
|
|
|
|
identical or equal as defined by java.lang.Object.equals.
|
|
|
|
|
2012-12-21 20:36:24 +00:00
|
|
|
"dumpCounters" - will dump the debug counters' current values to
|
|
|
|
stdout.
|
|
|
|
|
|
|
|
Currently we count number of ScriptObjects in the system, number of
|
|
|
|
Scope objects in the system, number of ScriptObject listeners added,
|
|
|
|
removed and dead (without references).
|
|
|
|
|
|
|
|
We also count number of ScriptFunctions, ScriptFunction invocations
|
|
|
|
and ScriptFunction allocations.
|
|
|
|
|
|
|
|
Furthermore we count PropertyMap statistics: how many property maps
|
|
|
|
exist, how many times were property maps cloned, how many times did
|
|
|
|
the property map history cache hit, prevent new allocations, how many
|
|
|
|
prototype invalidations were done, how many time the property map
|
|
|
|
proto cache hit.
|
|
|
|
|
|
|
|
Finally we count callsite misses on a per callsite bases, which occur
|
|
|
|
when a callsite has to be relinked, due to a previous assumption of
|
|
|
|
object layout being invalidated.
|
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
"getContext" - return the current Nashorn context.
|
2012-12-21 20:36:24 +00:00
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
"equalWithoutType" - Returns true if if the two objects are both
|
|
|
|
property maps, and they have identical properties in the same order,
|
|
|
|
but allows the properties to differ in their types.
|
2012-12-21 20:36:24 +00:00
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
"diffPropertyMaps" Returns a diagnostic string representing the difference
|
|
|
|
of two property maps.
|
|
|
|
|
|
|
|
"getClass" - Returns the Java class of an object, or undefined if null.
|
|
|
|
|
|
|
|
"toJavaString" - Returns the Java toString representation of an object.
|
|
|
|
|
|
|
|
"toIdentString" - Returns a string representation of an object consisting
|
|
|
|
of its java class name and hash code.
|
|
|
|
|
|
|
|
"getListenerCount" - Return the number of property listeners for a
|
|
|
|
script object.
|
2012-12-21 20:36:24 +00:00
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
"getEventQueueCapacity" - Get the capacity of the event queue.
|
|
|
|
|
|
|
|
"setEventQueueCapacity" - Set the event queue capacity.
|
|
|
|
|
|
|
|
"addRuntimeEvent" - Add a runtime event to the runtime event queue.
|
|
|
|
The queue has a fixed size (see -Dnashorn.runtime.event.queue.size)
|
|
|
|
and the oldest entry will be thrown out of the queue is about to overflow.
|
|
|
|
|
|
|
|
"expandEventQueueCapacity" - Expands the event queue capacity,
|
|
|
|
or truncates if capacity is lower than current capacity. Then only
|
|
|
|
the newest entries are kept.
|
|
|
|
|
|
|
|
"clearRuntimeEvents" - Clear the runtime event queue.
|
|
|
|
|
|
|
|
"removeRuntimeEvent" - Remove a specific runtime event from the event queue.
|
|
|
|
|
|
|
|
"getRuntimeEvents" - Return all runtime events in the queue as an array.
|
|
|
|
|
|
|
|
"getLastRuntimeEvent" - Return the last runtime event in the queue.
|
2012-12-21 20:36:24 +00:00
|
|
|
|
|
|
|
|
2013-08-23 13:46:09 +00:00
|
|
|
SYSTEM PROPERTY: -Dnashorn.methodhandles.debug.stacktrace
|
2012-12-21 20:36:24 +00:00
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
This enhances methodhandles logging (see below) to also dump the
|
|
|
|
stack trace for every instrumented method handle operation.
|
|
|
|
Warning: This is enormously verbose, but provides a pretty
|
2012-12-21 20:36:24 +00:00
|
|
|
decent "grep:able" picture of where the calls are coming from.
|
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
|
|
|
|
SYSTEM PROPERTY: -Dnashorn.cce
|
|
|
|
|
|
|
|
Setting this system property causes the Nashorn linker to rely on
|
|
|
|
ClassCastExceptions for triggering a callsite relink. If not set, the linker
|
|
|
|
will add an explicit instanceof guard.
|
|
|
|
|
|
|
|
|
|
|
|
SYSTEM PROPERTY: -Dnashorn.spill.threshold=<x>
|
|
|
|
|
|
|
|
This property sets the number of fields in an object from which to use
|
|
|
|
generic array based spill storage instead of Java fields. The default value
|
|
|
|
is 256.
|
2012-12-21 20:36:24 +00:00
|
|
|
|
|
|
|
|
2013-08-23 13:46:09 +00:00
|
|
|
SYSTEM PROPERTY: -Dnashorn.tcs.miss.samplePercent=<x>
|
2012-12-21 20:36:24 +00:00
|
|
|
|
|
|
|
When running with the trace callsite option (-tcs), Nashorn will count
|
|
|
|
and instrument any callsite misses that require relinking. As the
|
|
|
|
number of relinks is large and usually produces a lot of output, this
|
|
|
|
system property can be used to constrain the percentage of misses that
|
|
|
|
should be logged. Typically this is set to 1 or 5 (percent). 1% is the
|
|
|
|
default value.
|
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
SYSTEM PROPERTY: -Dnashorn.persistent.code.cache
|
|
|
|
|
|
|
|
This property can be used to set the directory where Nashorn stores
|
|
|
|
serialized script classes generated with the -pcc/--persistent-code-cache
|
|
|
|
option. The default directory name is "nashorn_code_cache".
|
2012-12-21 20:36:24 +00:00
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
|
|
|
|
SYSTEM PROPERTY: -Dnashorn.typeInfo.maxFiles
|
|
|
|
|
|
|
|
Maximum number of files to store in the type info cache. The type info cache
|
|
|
|
is used to cache type data of JavaScript functions when running with
|
|
|
|
optimistic types (-ot/--optimistic-types). There is one file per JavaScript
|
|
|
|
function in the cache.
|
|
|
|
|
|
|
|
The default value is 0 which means the feature is disabled. Setting this
|
|
|
|
to something like 20000 is probably good enough for most applications and
|
|
|
|
will usually cap the cache directory to about 80MB presuming a 4kB
|
|
|
|
filesystem allocation unit. Set this to "unlimited" to run without limit.
|
|
|
|
|
|
|
|
If the value is not 0 or "unlimited", Nashorn will spawn a cleanup thread
|
|
|
|
that makes sure the number of files in the cache does not exceed the given
|
|
|
|
value by deleting the least recently modified files.
|
|
|
|
|
|
|
|
|
|
|
|
SYSTEM PROPERTY: -Dnashorn.typeInfo.cacheDir
|
|
|
|
|
|
|
|
This property can be used to set the directory where Nashorn stores the
|
|
|
|
type info cache when -Dnashorn.typeInfo.maxFiles is set to a nonzero
|
|
|
|
value. The default location is platform specific. On Windows, it is
|
|
|
|
"${java.io.tmpdir}\com.oracle.java.NashornTypeInfo". On Linux and
|
|
|
|
Solaris it is "~/.cache/com.oracle.java.NashornTypeInfo". On Mac OS X,
|
|
|
|
it is "~/Library/Caches/com.oracle.java.NashornTypeInfo".
|
|
|
|
|
|
|
|
|
|
|
|
SYSTEM PROPERTY: -Dnashorn.typeInfo.cleanupDelaySeconds=<value>
|
|
|
|
|
|
|
|
This sets the delay between cleanups of the typeInfo cache, in seconds.
|
|
|
|
The default delay is 20 seconds.
|
|
|
|
|
|
|
|
|
|
|
|
SYSTEM PROPERTY: -Dnashorn.profilefile=<filename>
|
2012-12-21 20:36:24 +00:00
|
|
|
|
|
|
|
When running with the profile callsite options (-pcs), Nashorn will
|
|
|
|
dump profiling data for all callsites to stderr as a shutdown hook. To
|
|
|
|
instead redirect this to a file, specify the path to the file using
|
|
|
|
this system property.
|
|
|
|
|
|
|
|
|
2013-08-23 13:46:09 +00:00
|
|
|
SYSTEM_PROPERTY: -Dnashorn.regexp.impl=[jdk|joni]
|
2013-02-22 16:00:22 +00:00
|
|
|
|
|
|
|
This property defines the regular expression engine to be used by
|
2013-08-23 13:46:09 +00:00
|
|
|
Nashorn. Set this flag to "jdk" to get an implementation based on the
|
2013-02-22 16:00:22 +00:00
|
|
|
JDK's java.util.regex package. Set this property to "joni" to install
|
|
|
|
an implementation based on Joni, the regular expression engine used by
|
2013-08-23 13:46:09 +00:00
|
|
|
the JRuby project. The default value for this flag is "joni"
|
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
SYSTEM PROPERTY: -Dnashorn.runtime.event.queue.size=<value>
|
|
|
|
|
|
|
|
Nashorn provides a fixed sized runtime event queue for debugging purposes.
|
|
|
|
See -Dnashorn.debug for methods to access the event queue.
|
|
|
|
The default value is 1024.
|
2013-02-22 16:00:22 +00:00
|
|
|
|
2016-08-08 10:51:44 +00:00
|
|
|
SYSTEM PROPERTY: -Dnashorn.anonymous.classes.threshold=<value>
|
|
|
|
|
|
|
|
Nashorn can use anonymous classes for loading compiled scripts, depending
|
|
|
|
on the --anonymous-classes=[auto|true|false] option. Anonymous classes load
|
|
|
|
faster, but the loaded classes get less optimization applied to them and
|
|
|
|
therefore usually run slower. In the default "auto" setting, scripts are
|
|
|
|
loaded as anonymous classes if the script size does not exceed 512 bytes.
|
|
|
|
The above system property allows to set this threshold to a user defined
|
|
|
|
value.
|
|
|
|
|
2012-12-21 20:36:24 +00:00
|
|
|
===============
|
|
|
|
2. The loggers.
|
|
|
|
===============
|
|
|
|
|
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes
Lower suffered from being a "God class" trying to do everything at once. As Nashorn code generation has grown, so has Lower. It does several post processing passes, tries to do several things at once even though all type information isn't in place, adjusting state afterwards and so on. It also performs control flow analysis, type attribution and constant folding, and everything else code generation related before byte code emission. I have now separated the compilation process into Lower (create low level nodes from high level ones, copy code such as finally block inlining etc), Attr (assign types and symbols to all nodes - freeze slot and scope information) and FinalizeTypes (insert explicit casts, specialize invoke dynamic types for scope accesses). I've removed the kludgy AccessSpecializer, as this now integrates naturally with typing. Everything is now much easier to read and each module performs only one thing. I have added separate loggers for the separate tiers. In the process I have also fixed: (1) problems with type coercion (see test/script/basic/typecoercion.js, basically our coercion was too late and our symbol inference was erroneous. This only manifested itself in very rare occasions where toNumber coercion has side effects, such as for example when valueOf is overridden) (2) copying literal nodes (literal copy did not use the superclass copy, which made all the Node specific fields not to be copied (3) erroneous literal tokenization (literals shouldn't always just inherit token information from whatever node that creates them) (4) splitter weighnodes - unary nodes were considered weightless (4) removed the hateful and kludgy "VarNode.shouldAppend", which really isn't needed when we have an attribution phase that determines self reference symbols (the only thing it was used for) (5) duplicate line number issues in the parser (6) convert bug in CodeGenerator for intermediate results of scope accesses (see test/script/basic/access-specializer.js) ... Several of these things just stopped being problems with the new architecture "can't happen anymore" and are not bug fixes per se. All tests run. No performance regressions exist that I've been able to measure. Some increases in performance were measured, but in the statistical margin of error (which is very wide as HotSpot currently has warmup issues with LambdaForms/invoke dynamic). Compile speed has not measurably increased.
Reviewed-by: jlaskey, attila
2013-01-30 11:26:45 +00:00
|
|
|
It is very simple to create your own logger. Use the DebugLogger class
|
|
|
|
and give the subsystem name as a constructor argument.
|
|
|
|
|
2012-12-21 20:36:24 +00:00
|
|
|
The Nashorn loggers can be used to print per-module or per-subsystem
|
|
|
|
debug information with different levels of verbosity. The loggers for
|
|
|
|
a given subsystem are available are enabled by using
|
|
|
|
|
|
|
|
--log=<systemname>[:<level>]
|
|
|
|
|
|
|
|
on the command line.
|
|
|
|
|
|
|
|
Here <systemname> identifies the name of the subsystem to be logged
|
|
|
|
and the optional colon and level argument is a standard
|
|
|
|
java.util.logging.Level name (severe, warning, info, config, fine,
|
|
|
|
finer, finest). If the level is left out for a particular subsystem,
|
|
|
|
it defaults to "info". Any log message logged as the level or a level
|
|
|
|
that is more important will be output to stderr by the logger.
|
|
|
|
|
|
|
|
Several loggers can be enabled by a single command line option, by
|
|
|
|
putting a comma after each subsystem/level tuple (or each subsystem if
|
|
|
|
level is unspecified). The --log option can also be given multiple
|
|
|
|
times on the same command line, with the same effect.
|
|
|
|
|
|
|
|
For example: --log=codegen,fields:finest is equivalent to
|
|
|
|
--log=codegen:info --log=fields:finest
|
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
The following is an incomplete list of subsystems that currently
|
|
|
|
support logging. Look for classes implementing
|
|
|
|
jdk.nashorn.internal.runtime.logging.Loggable for more loggers.
|
2012-12-21 20:36:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
* compiler
|
|
|
|
|
|
|
|
The compiler is in charge of turning source code and function nodes
|
|
|
|
into byte code, and installs the classes into a class loader
|
|
|
|
controlled from the Context. Log messages are, for example, about
|
|
|
|
things like new compile units being allocated. The compiler has global
|
|
|
|
settings that all the tiers of codegen (e.g. Lower and CodeGenerator)
|
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes
Lower suffered from being a "God class" trying to do everything at once. As Nashorn code generation has grown, so has Lower. It does several post processing passes, tries to do several things at once even though all type information isn't in place, adjusting state afterwards and so on. It also performs control flow analysis, type attribution and constant folding, and everything else code generation related before byte code emission. I have now separated the compilation process into Lower (create low level nodes from high level ones, copy code such as finally block inlining etc), Attr (assign types and symbols to all nodes - freeze slot and scope information) and FinalizeTypes (insert explicit casts, specialize invoke dynamic types for scope accesses). I've removed the kludgy AccessSpecializer, as this now integrates naturally with typing. Everything is now much easier to read and each module performs only one thing. I have added separate loggers for the separate tiers. In the process I have also fixed: (1) problems with type coercion (see test/script/basic/typecoercion.js, basically our coercion was too late and our symbol inference was erroneous. This only manifested itself in very rare occasions where toNumber coercion has side effects, such as for example when valueOf is overridden) (2) copying literal nodes (literal copy did not use the superclass copy, which made all the Node specific fields not to be copied (3) erroneous literal tokenization (literals shouldn't always just inherit token information from whatever node that creates them) (4) splitter weighnodes - unary nodes were considered weightless (4) removed the hateful and kludgy "VarNode.shouldAppend", which really isn't needed when we have an attribution phase that determines self reference symbols (the only thing it was used for) (5) duplicate line number issues in the parser (6) convert bug in CodeGenerator for intermediate results of scope accesses (see test/script/basic/access-specializer.js) ... Several of these things just stopped being problems with the new architecture "can't happen anymore" and are not bug fixes per se. All tests run. No performance regressions exist that I've been able to measure. Some increases in performance were measured, but in the statistical margin of error (which is very wide as HotSpot currently has warmup issues with LambdaForms/invoke dynamic). Compile speed has not measurably increased.
Reviewed-by: jlaskey, attila
2013-01-30 11:26:45 +00:00
|
|
|
use.s
|
2012-12-21 20:36:24 +00:00
|
|
|
|
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
* recompile
|
|
|
|
|
|
|
|
This logger shows information about recompilation of scripts and
|
|
|
|
functions at runtime. Recompilation may happen because a function
|
|
|
|
was called with different parameter types, or because an optimistic
|
|
|
|
assumption failed while executing a function with -ot/--optimistic-types.
|
|
|
|
|
|
|
|
|
2012-12-21 20:36:24 +00:00
|
|
|
* codegen
|
|
|
|
|
|
|
|
The code generator is the emitter stage of the code pipeline, and
|
|
|
|
turns the lowest tier of a FunctionNode into bytecode. Codegen logging
|
|
|
|
shows byte codes as they are being emitted, line number information
|
|
|
|
and jumps. It also shows the contents of the bytecode stack prior to
|
|
|
|
each instruction being emitted. This is a good debugging aid. For
|
|
|
|
example:
|
|
|
|
|
|
|
|
[codegen] #41 line:2 (f)_afc824e
|
|
|
|
[codegen] #42 load symbol x slot=2
|
|
|
|
[codegen] #43 {1:O} load int 0
|
|
|
|
[codegen] #44 {2:I O} dynamic_runtime_call GT:ZOI_I args=2 returnType=boolean
|
|
|
|
[codegen] #45 signature (Ljava/lang/Object;I)Z
|
|
|
|
[codegen] #46 {1:Z} ifeq ternary_false_5402fe28
|
|
|
|
[codegen] #47 load symbol x slot=2
|
|
|
|
[codegen] #48 {1:O} goto ternary_exit_107c1f2f
|
|
|
|
[codegen] #49 ternary_false_5402fe28
|
|
|
|
[codegen] #50 load symbol x slot=2
|
|
|
|
[codegen] #51 {1:O} convert object -> double
|
|
|
|
[codegen] #52 {1:D} neg
|
|
|
|
[codegen] #53 {1:D} convert double -> object
|
|
|
|
[codegen] #54 {1:O} ternary_exit_107c1f2f
|
|
|
|
[codegen] #55 {1:O} return object
|
|
|
|
|
|
|
|
shows a ternary node being generated for the sequence "return x > 0 ?
|
|
|
|
x : -x"
|
|
|
|
|
|
|
|
The first number on the log line is a unique monotonically increasing
|
|
|
|
emission id per bytecode. There is no guarantee this is the same id
|
|
|
|
between runs. depending on non deterministic code
|
|
|
|
execution/compilation, but for small applications it usually is. If
|
|
|
|
the system variable -Dnashorn.codegen.debug.trace=<x> is set, where x
|
|
|
|
is a bytecode emission id, a stack trace will be shown as the
|
|
|
|
particular bytecode is about to be emitted. This can be a quick way to
|
|
|
|
determine where it comes from without attaching the debugger. "Who
|
|
|
|
generated that neg?"
|
|
|
|
|
|
|
|
The --log=codegen option is equivalent to setting the system variable
|
|
|
|
"nashorn.codegen.debug" to true.
|
|
|
|
|
2013-08-23 13:46:09 +00:00
|
|
|
* fold
|
|
|
|
|
|
|
|
Shows constant folding taking place before lowering
|
2012-12-21 20:36:24 +00:00
|
|
|
|
|
|
|
* lower
|
|
|
|
|
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes
Lower suffered from being a "God class" trying to do everything at once. As Nashorn code generation has grown, so has Lower. It does several post processing passes, tries to do several things at once even though all type information isn't in place, adjusting state afterwards and so on. It also performs control flow analysis, type attribution and constant folding, and everything else code generation related before byte code emission. I have now separated the compilation process into Lower (create low level nodes from high level ones, copy code such as finally block inlining etc), Attr (assign types and symbols to all nodes - freeze slot and scope information) and FinalizeTypes (insert explicit casts, specialize invoke dynamic types for scope accesses). I've removed the kludgy AccessSpecializer, as this now integrates naturally with typing. Everything is now much easier to read and each module performs only one thing. I have added separate loggers for the separate tiers. In the process I have also fixed: (1) problems with type coercion (see test/script/basic/typecoercion.js, basically our coercion was too late and our symbol inference was erroneous. This only manifested itself in very rare occasions where toNumber coercion has side effects, such as for example when valueOf is overridden) (2) copying literal nodes (literal copy did not use the superclass copy, which made all the Node specific fields not to be copied (3) erroneous literal tokenization (literals shouldn't always just inherit token information from whatever node that creates them) (4) splitter weighnodes - unary nodes were considered weightless (4) removed the hateful and kludgy "VarNode.shouldAppend", which really isn't needed when we have an attribution phase that determines self reference symbols (the only thing it was used for) (5) duplicate line number issues in the parser (6) convert bug in CodeGenerator for intermediate results of scope accesses (see test/script/basic/access-specializer.js) ... Several of these things just stopped being problems with the new architecture "can't happen anymore" and are not bug fixes per se. All tests run. No performance regressions exist that I've been able to measure. Some increases in performance were measured, but in the statistical margin of error (which is very wide as HotSpot currently has warmup issues with LambdaForms/invoke dynamic). Compile speed has not measurably increased.
Reviewed-by: jlaskey, attila
2013-01-30 11:26:45 +00:00
|
|
|
This is the first lowering pass.
|
|
|
|
|
|
|
|
Lower is a code generation pass that turns high level IR nodes into
|
|
|
|
lower level one, for example substituting comparisons to RuntimeNodes
|
|
|
|
and inlining finally blocks.
|
|
|
|
|
|
|
|
Lower is also responsible for determining control flow information
|
|
|
|
like end points.
|
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
* symbols
|
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes
Lower suffered from being a "God class" trying to do everything at once. As Nashorn code generation has grown, so has Lower. It does several post processing passes, tries to do several things at once even though all type information isn't in place, adjusting state afterwards and so on. It also performs control flow analysis, type attribution and constant folding, and everything else code generation related before byte code emission. I have now separated the compilation process into Lower (create low level nodes from high level ones, copy code such as finally block inlining etc), Attr (assign types and symbols to all nodes - freeze slot and scope information) and FinalizeTypes (insert explicit casts, specialize invoke dynamic types for scope accesses). I've removed the kludgy AccessSpecializer, as this now integrates naturally with typing. Everything is now much easier to read and each module performs only one thing. I have added separate loggers for the separate tiers. In the process I have also fixed: (1) problems with type coercion (see test/script/basic/typecoercion.js, basically our coercion was too late and our symbol inference was erroneous. This only manifested itself in very rare occasions where toNumber coercion has side effects, such as for example when valueOf is overridden) (2) copying literal nodes (literal copy did not use the superclass copy, which made all the Node specific fields not to be copied (3) erroneous literal tokenization (literals shouldn't always just inherit token information from whatever node that creates them) (4) splitter weighnodes - unary nodes were considered weightless (4) removed the hateful and kludgy "VarNode.shouldAppend", which really isn't needed when we have an attribution phase that determines self reference symbols (the only thing it was used for) (5) duplicate line number issues in the parser (6) convert bug in CodeGenerator for intermediate results of scope accesses (see test/script/basic/access-specializer.js) ... Several of these things just stopped being problems with the new architecture "can't happen anymore" and are not bug fixes per se. All tests run. No performance regressions exist that I've been able to measure. Some increases in performance were measured, but in the statistical margin of error (which is very wide as HotSpot currently has warmup issues with LambdaForms/invoke dynamic). Compile speed has not measurably increased.
Reviewed-by: jlaskey, attila
2013-01-30 11:26:45 +00:00
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
The symbols logger tracks the assignment os symbols to identifiers.
|
2012-12-21 20:36:24 +00:00
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
* scopedepths
|
2012-12-21 20:36:24 +00:00
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
This logs the calculation of scope depths for non-local symbols.
|
2012-12-21 20:36:24 +00:00
|
|
|
|
|
|
|
* fields
|
|
|
|
|
|
|
|
The --log=fields option (at info level) is equivalent to setting the
|
|
|
|
system variable "nashorn.fields.debug" to true. At the info level it
|
|
|
|
will only show info about type assumptions that were invalidated. If
|
|
|
|
the level is set to finest, it will also trace every AccessorProperty
|
|
|
|
getter and setter in the program, show arguments, return values
|
|
|
|
etc. It will also show the internal representation of respective field
|
|
|
|
(Object in the normal case, unless running with the dual field
|
2013-01-11 09:40:51 +00:00
|
|
|
representation)
|
2013-08-23 13:46:09 +00:00
|
|
|
|
2014-05-21 14:12:40 +00:00
|
|
|
* time
|
|
|
|
|
|
|
|
This enables timers for various phases of script compilation. The timers
|
|
|
|
will be dumped when the Nashorn process exits. We see a percentage value
|
|
|
|
of how much time was spent not executing bytecode (i.e. compilation and
|
|
|
|
internal tasks) at the end of the report.
|
|
|
|
|
|
|
|
A finer level than "info" will show individual compilation timings as they
|
|
|
|
happen.
|
|
|
|
|
|
|
|
Here is an example:
|
|
|
|
|
|
|
|
[time] Accumulated complation phase Timings:
|
|
|
|
[time]
|
|
|
|
[time] 'JavaScript Parsing' 1076 ms
|
|
|
|
[time] 'Constant Folding' 159 ms
|
|
|
|
[time] 'Control Flow Lowering' 303 ms
|
|
|
|
[time] 'Program Point Calculation' 282 ms
|
|
|
|
[time] 'Builtin Replacement' 71 ms
|
|
|
|
[time] 'Code Splitting' 670 ms
|
|
|
|
[time] 'Symbol Assignment' 474 ms
|
|
|
|
[time] 'Scope Depth Computation' 249 ms
|
|
|
|
[time] 'Optimistic Type Assignment' 186 ms
|
|
|
|
[time] 'Local Variable Type Calculation' 526 ms
|
|
|
|
[time] 'Bytecode Generation' 5177 ms
|
|
|
|
[time] 'Class Installation' 1854 ms
|
|
|
|
[time]
|
|
|
|
[time] Total runtime: 11994 ms (Non-runtime: 11027 ms [91%])
|
2013-08-23 13:46:09 +00:00
|
|
|
|
2014-10-23 15:25:39 +00:00
|
|
|
* methodhandles
|
|
|
|
|
|
|
|
If this logger is enabled, each MethodHandle related call that uses
|
|
|
|
the java.lang.invoke package gets its MethodHandle intercepted and an
|
|
|
|
instrumentation printout of arguments and return value appended to
|
|
|
|
it. This shows exactly which method handles are executed and from
|
|
|
|
where. (Also MethodTypes and SwitchPoints).
|
|
|
|
|
|
|
|
* classcache
|
|
|
|
|
|
|
|
This logger shows information about reusing code classes using the
|
|
|
|
in-memory class cache. Nashorn will try to avoid compilation of
|
|
|
|
scripts by using existing classes. This can significantly improve
|
|
|
|
performance when repeatedly evaluating the same script.
|
|
|
|
|
2013-08-23 13:46:09 +00:00
|
|
|
=======================
|
|
|
|
3. Undocumented options
|
|
|
|
=======================
|
|
|
|
|
|
|
|
Here follows a short description of undocumented options for Nashorn.
|
|
|
|
To see a list of all undocumented options, use the (undocumented) flag
|
|
|
|
"-xhelp".
|
|
|
|
|
|
|
|
i.e. jjs -xhelp or java -jar nashorn.jar -xhelp
|
|
|
|
|
|
|
|
Undocumented options are not guaranteed to work, run correctly or be
|
|
|
|
bug free. They are experimental and for internal or debugging use.
|
|
|
|
They are also subject to change without notice.
|
|
|
|
|
|
|
|
In practice, though, all options below not explicitly documented as
|
|
|
|
EXPERIMENTAL can be relied upon, for example --dump-on-error is useful
|
|
|
|
for any JavaScript/Nashorn developer, but there is no guarantee.
|
|
|
|
|
|
|
|
A short summary follows:
|
|
|
|
|
|
|
|
-D (-Dname=value. Set a system property. This option can be repeated.)
|
|
|
|
|
|
|
|
-ccs, --class-cache-size (Size of the Class cache size per global scope.)
|
|
|
|
|
|
|
|
-cp, -classpath (-cp path. Specify where to find user class files.)
|
|
|
|
|
2014-05-27 19:25:07 +00:00
|
|
|
-co, --compile-only (Compile without running.)
|
2013-08-23 13:46:09 +00:00
|
|
|
param: [true|false] default: false
|
|
|
|
|
2014-05-27 19:25:07 +00:00
|
|
|
-d, --dump-debug-dir (specify a destination directory to dump class files.)
|
2013-08-23 13:46:09 +00:00
|
|
|
param: <path>
|
|
|
|
|
|
|
|
--debug-lines (Generate line number table in .class files.)
|
|
|
|
param: [true|false] default: true
|
|
|
|
|
|
|
|
--debug-locals (Generate local variable table in .class files.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|
|
|
|
-doe, -dump-on-error (Dump a stack trace on errors.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|
|
|
|
--early-lvalue-error (invalid lvalue expressions should be reported as early errors.)
|
|
|
|
param: [true|false] default: true
|
|
|
|
|
|
|
|
--empty-statements (Preserve empty statements in AST.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|
|
|
|
-fv, -fullversion (Print full version info of Nashorn.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|
|
|
|
--function-statement-error (Report an error when function declaration is used as a statement.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|
|
|
|
--function-statement-warning (Warn when function declaration is used as a statement.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|
|
|
|
-fx (Launch script as an fx application.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|
|
|
|
--global-per-engine (Use single Global instance per script engine instance.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|
|
|
|
-h, -help (Print help for command line flags.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|
|
|
|
--loader-per-compile (Create a new class loader per compile.)
|
|
|
|
param: [true|false] default: true
|
|
|
|
|
|
|
|
-l, --locale (Set Locale for script execution.)
|
|
|
|
param: <locale> default: en-US
|
|
|
|
|
|
|
|
--log (Enable logging of a given level for a given number of sub systems.
|
2014-05-27 19:25:07 +00:00
|
|
|
[for example: --log=fields:finest,codegen:info].)
|
2013-08-23 13:46:09 +00:00
|
|
|
param: <module:level>,*
|
|
|
|
|
2014-05-27 19:25:07 +00:00
|
|
|
-nj, --no-java (Disable Java support.)
|
2013-08-23 13:46:09 +00:00
|
|
|
param: [true|false] default: false
|
|
|
|
|
2014-05-27 19:25:07 +00:00
|
|
|
-nse, --no-syntax-extensions (Disallow non-standard syntax extensions.)
|
2013-08-23 13:46:09 +00:00
|
|
|
param: [true|false] default: false
|
|
|
|
|
2014-05-27 19:25:07 +00:00
|
|
|
-nta, --no-typed-arrays (Disable typed arrays support.)
|
2013-08-23 13:46:09 +00:00
|
|
|
param: [true|false] default: false
|
|
|
|
|
|
|
|
--parse-only (Parse without compiling.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|
|
|
|
--print-ast (Print abstract syntax tree.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|
2014-05-27 19:25:07 +00:00
|
|
|
-pc, --print-code (Print generated bytecode. If a directory is specified, nothing will
|
|
|
|
be dumped to stderr. Also, in that case, .dot files will be generated
|
|
|
|
for all functions or for the function with the specified name only.)
|
|
|
|
param: [dir:<output-dir>,function:<name>]
|
2013-08-23 13:46:09 +00:00
|
|
|
|
|
|
|
--print-lower-ast (Print lowered abstract syntax tree.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|
2014-05-27 19:25:07 +00:00
|
|
|
-plp, --print-lower-parse (Print the parse tree after lowering.)
|
2013-08-23 13:46:09 +00:00
|
|
|
param: [true|false] default: false
|
|
|
|
|
|
|
|
--print-mem-usage (Print memory usage of IR after each compile stage.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|
|
|
|
--print-no-newline (Print function will not print new line char.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|
2014-05-27 19:25:07 +00:00
|
|
|
-pp, --print-parse (Print the parse tree.)
|
2013-08-23 13:46:09 +00:00
|
|
|
param: [true|false] default: false
|
|
|
|
|
|
|
|
--print-symbols (Print the symbol table.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|
|
|
|
-pcs, --profile-callsites (Dump callsite profile data.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|
|
|
|
-scripting (Enable scripting features.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|
2014-05-27 19:25:07 +00:00
|
|
|
--stderr (Redirect stderr to a filename or to another tty, e.g. stdout.)
|
2013-08-23 13:46:09 +00:00
|
|
|
param: <output console>
|
|
|
|
|
2014-05-27 19:25:07 +00:00
|
|
|
--stdout (Redirect stdout to a filename or to another tty, e.g. stderr.)
|
2013-08-23 13:46:09 +00:00
|
|
|
param: <output console>
|
|
|
|
|
|
|
|
-strict (Run scripts in strict mode.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|
|
|
|
-t, -timezone (Set timezone for script execution.)
|
|
|
|
param: <timezone> default: Europe/Stockholm
|
|
|
|
|
|
|
|
-tcs, --trace-callsites (Enable callsite trace mode. Options are: miss [trace callsite misses]
|
2014-05-27 19:25:07 +00:00
|
|
|
enterexit [trace callsite enter/exit], objects [print object properties].)
|
2013-08-23 13:46:09 +00:00
|
|
|
param: [=[option,]*]
|
|
|
|
|
2015-11-09 14:37:07 +00:00
|
|
|
-urt, --unstable-relink-threshold (Number of times a dynamic call site has to be relinked before it
|
|
|
|
is considered unstable, when the runtime will try to link it as
|
|
|
|
if it is megamorphic.)
|
|
|
|
|
2013-08-23 13:46:09 +00:00
|
|
|
--verify-code (Verify byte code before running.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|
|
|
|
-v, -version (Print version info of Nashorn.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|
|
|
|
-xhelp (Print extended help for command line flags.)
|
|
|
|
param: [true|false] default: false
|
|
|
|
|