mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-14 18:03:44 +00:00
8059813: Type Info Cache flag must must be documented
Reviewed-by: attila, jlaskey
This commit is contained in:
parent
5f5c28bf63
commit
02308fac34
@ -25,6 +25,14 @@ Example:
|
||||
> java -Dnashorn.args="--lazy-complation --log=compiler" large-java-app-with-nashorn.jar
|
||||
> ant -Dnashorn.args="--log=codegen" antjob
|
||||
|
||||
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.
|
||||
|
||||
|
||||
SYSTEM PROPERTY: -Dnashorn.unstable.relink.threshold=x
|
||||
|
||||
This property controls how many call site misses are allowed before a
|
||||
@ -42,533 +50,38 @@ be split into several classes in order not to run out of bytecode space.
|
||||
The default value is 0x8000 (32768).
|
||||
|
||||
|
||||
SYSTEM PROPERTY: -Dnashorn.compiler.intarithmetic
|
||||
SYSTEM PROPERTY: -Dnashorn.serialize.compression=<x>
|
||||
|
||||
(and integer arithmetic in general)
|
||||
|
||||
<currently disabled - this is being refactored for update releases>
|
||||
|
||||
Arithmetic operations in Nashorn (except bitwise ones) typically
|
||||
coerce the operands to doubles (as per the JavaScript spec). To switch
|
||||
this off and remain in integer mode, for example for "var x = a&b; var
|
||||
y = c&d; var z = x*y;", use this flag. This will force the
|
||||
multiplication of variables that are ints to be done with the IMUL
|
||||
bytecode and the result "z" to become an int.
|
||||
|
||||
WARNING: Note that is is experimental only to ensure that type support
|
||||
exists for all primitive types. The generated code is unsound. This
|
||||
will be the case until we do optimizations based on it. There is a CR
|
||||
in Nashorn to do better range analysis, and ensure that this is only
|
||||
done where the operation can't overflow into a wider type. Currently
|
||||
no overflow checking is done, so at the moment, until range analysis
|
||||
has been completed, this option is turned off.
|
||||
|
||||
We've experimented by using int arithmetic for everything and putting
|
||||
overflow checks afterwards, which would recompute the operation with
|
||||
the correct precision, but have yet to find a configuration where this
|
||||
is faster than just using doubles directly, even if the int operation
|
||||
does not overflow. Getting access to a JVM intrinsic that does branch
|
||||
on overflow would probably alleviate this.
|
||||
|
||||
The future:
|
||||
|
||||
We are transitioning to an optimistic type system that uses int
|
||||
arithmetic everywhere until proven wrong. The problem here is mostly
|
||||
catch an overflow exception and rolling back the state to a new method
|
||||
with less optimistic assumptions for an operation at a particular
|
||||
program point. This will most likely not be in the Java 8.0 release
|
||||
but likely end up in an update release
|
||||
|
||||
For Java 8, several java.lang.Math methods like addExact, subExact and
|
||||
mulExact are available to help us. Experiments intrinsifying these
|
||||
show a lot of promise, and we have devised a system that basically
|
||||
does on stack replacement with exceptions in bytecode to revert
|
||||
erroneous assumptions. An explanation of how this works and what we
|
||||
are doing can be found here:
|
||||
http://www.slideshare.net/lagergren/lagergren-jvmls2013final
|
||||
|
||||
Experiments with this show significant ~x2-3 performance increases on
|
||||
pretty much everything, provided that optimistic assumptions don't
|
||||
fail much. It will affect warmup time negatively, depending on how
|
||||
many erroneous too optimistic assumptions are placed in the code at
|
||||
compile time. We don't think this will be much of an issue.
|
||||
|
||||
For example for a small benchmark that repeatedly executes this
|
||||
method taken from the Crypto Octane benchmark
|
||||
|
||||
function am3(i,x,w,j,c,n) {
|
||||
var this_array = this.array;
|
||||
var w_array = w.array;
|
||||
var xl = x&0x3fff, xh = x>>14;
|
||||
while(--n >= 0) {
|
||||
var l = this_array[i]&0x3fff;
|
||||
var h = this_array[i++]>>14;
|
||||
var m = xh*l+h*xl;
|
||||
l = xl*l+((m&0x3fff)<<14)+w_array[j]+c;
|
||||
c = (l>>28)+(m>>14)+xh*h;
|
||||
w_array[j++] = l&0xfffffff;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
The performance increase more than doubles. We are also working hard
|
||||
with the code generation team in the Java Virtual Machine to fix
|
||||
things that are lacking in invokedynamic performance, which is another
|
||||
area where a lot of ongoing performance work takes place
|
||||
|
||||
"Pessimistic" bytecode for am3, guaranteed to be semantically correct:
|
||||
|
||||
// access flags 0x9
|
||||
public static am3(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
||||
L0
|
||||
LINENUMBER 12 L0
|
||||
ALOAD 0
|
||||
INVOKEDYNAMIC dyn:getProp|getElem|getMethod:array(Ljava/lang/Object;)Ljava/lang/Object; [
|
||||
// handle kind 0x6 : INVOKESTATIC
|
||||
jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
|
||||
// arguments:
|
||||
0
|
||||
]
|
||||
ASTORE 8
|
||||
L1
|
||||
LINENUMBER 13 L1
|
||||
ALOAD 3
|
||||
INVOKEDYNAMIC dyn:getProp|getElem|getMethod:array(Ljava/lang/Object;)Ljava/lang/Object; [
|
||||
// handle kind 0x6 : INVOKESTATIC
|
||||
jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
|
||||
// arguments:
|
||||
0
|
||||
]
|
||||
ASTORE 9
|
||||
L2
|
||||
LINENUMBER 14 L2
|
||||
ALOAD 2
|
||||
INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toInt32 (Ljava/lang/Object;)I
|
||||
SIPUSH 16383
|
||||
IAND
|
||||
ISTORE 10
|
||||
ALOAD 2
|
||||
INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toInt32 (Ljava/lang/Object;)I
|
||||
BIPUSH 14
|
||||
ISHR
|
||||
ISTORE 11
|
||||
L3
|
||||
LINENUMBER 15 L3
|
||||
GOTO L4
|
||||
L5
|
||||
LINENUMBER 16 L5
|
||||
FRAME FULL [java/lang/Object java/lang/Object java/lang/Object java/lang/Object java/lang/Object java/lang/Object java/lang/Double T java/lang/Object java/lang/Object I I] []
|
||||
ALOAD 8
|
||||
ALOAD 1
|
||||
INVOKEDYNAMIC dyn:getElem|getProp|getMethod(Ljava/lang/Object;Ljava/lang/Object;)I [
|
||||
// handle kind 0x6 : INVOKESTATIC
|
||||
jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
|
||||
// arguments:
|
||||
0
|
||||
]
|
||||
SIPUSH 16383
|
||||
IAND
|
||||
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
|
||||
ASTORE 12
|
||||
L6
|
||||
LINENUMBER 17 L6
|
||||
ALOAD 8
|
||||
ALOAD 1
|
||||
INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toNumber (Ljava/lang/Object;)D
|
||||
DUP2
|
||||
DCONST_1
|
||||
DADD
|
||||
INVOKESTATIC java/lang/Double.valueOf (D)Ljava/lang/Double;
|
||||
ASTORE 1
|
||||
INVOKEDYNAMIC dyn:getElem|getProp|getMethod(Ljava/lang/Object;D)I [
|
||||
// handle kind 0x6 : INVOKESTATIC
|
||||
jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
|
||||
// arguments:
|
||||
0
|
||||
]
|
||||
BIPUSH 14
|
||||
ISHR
|
||||
ISTORE 13
|
||||
L7
|
||||
LINENUMBER 18 L7
|
||||
ILOAD 11
|
||||
I2D
|
||||
ALOAD 12
|
||||
INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toNumber (Ljava/lang/Object;)D
|
||||
DMUL
|
||||
ILOAD 13
|
||||
I2D
|
||||
ILOAD 10
|
||||
I2D
|
||||
DMUL
|
||||
DADD
|
||||
DSTORE 14
|
||||
L8
|
||||
LINENUMBER 19 L8
|
||||
ILOAD 10
|
||||
I2D
|
||||
ALOAD 12
|
||||
INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toNumber (Ljava/lang/Object;)D
|
||||
DMUL
|
||||
DLOAD 14
|
||||
INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toInt32 (D)I
|
||||
SIPUSH 16383
|
||||
IAND
|
||||
BIPUSH 14
|
||||
ISHL
|
||||
I2D
|
||||
DADD
|
||||
ALOAD 9
|
||||
ALOAD 4
|
||||
INVOKEDYNAMIC dyn:getElem|getProp|getMethod(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; [
|
||||
// handle kind 0x6 : INVOKESTATIC
|
||||
jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
|
||||
// arguments:
|
||||
0
|
||||
]
|
||||
INVOKEDYNAMIC ADD:ODO_D(DLjava/lang/Object;)Ljava/lang/Object; [
|
||||
// handle kind 0x6 : INVOKESTATIC
|
||||
jdk/nashorn/internal/runtime/linker/Bootstrap.runtimeBootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;)
|
||||
// arguments: none
|
||||
]
|
||||
ALOAD 5
|
||||
INVOKEDYNAMIC ADD:OOO_I(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; [
|
||||
// handle kind 0x6 : INVOKESTATIC
|
||||
jdk/nashorn/internal/runtime/linker/Bootstrap.runtimeBootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;)
|
||||
// arguments: none
|
||||
]
|
||||
ASTORE 12
|
||||
L9
|
||||
LINENUMBER 20 L9
|
||||
ALOAD 12
|
||||
INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toInt32 (Ljava/lang/Object;)I
|
||||
BIPUSH 28
|
||||
ISHR
|
||||
I2D
|
||||
DLOAD 14
|
||||
INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toInt32 (D)I
|
||||
BIPUSH 14
|
||||
ISHR
|
||||
I2D
|
||||
DADD
|
||||
ILOAD 11
|
||||
I2D
|
||||
ILOAD 13
|
||||
I2D
|
||||
DMUL
|
||||
DADD
|
||||
INVOKESTATIC java/lang/Double.valueOf (D)Ljava/lang/Double;
|
||||
ASTORE 5
|
||||
L10
|
||||
LINENUMBER 21 L10
|
||||
ALOAD 9
|
||||
ALOAD 4
|
||||
INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toNumber (Ljava/lang/Object;)D
|
||||
DUP2
|
||||
DCONST_1
|
||||
DADD
|
||||
INVOKESTATIC java/lang/Double.valueOf (D)Ljava/lang/Double;
|
||||
ASTORE 4
|
||||
ALOAD 12
|
||||
INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toInt32 (Ljava/lang/Object;)I
|
||||
LDC 268435455
|
||||
IAND
|
||||
INVOKEDYNAMIC dyn:setElem|setProp(Ljava/lang/Object;DI)V [
|
||||
// handle kind 0x6 : INVOKESTATIC
|
||||
jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
|
||||
// arguments:
|
||||
0
|
||||
]
|
||||
L4
|
||||
FRAME FULL [java/lang/Object java/lang/Object java/lang/Object java/lang/Object java/lang/Object java/lang/Object java/lang/Object T java/lang/Object java/lang/Object I I] []
|
||||
ALOAD 6
|
||||
INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toNumber (Ljava/lang/Object;)D
|
||||
LDC -1.0
|
||||
DADD
|
||||
DUP2
|
||||
INVOKESTATIC java/lang/Double.valueOf (D)Ljava/lang/Double;
|
||||
ASTORE 6
|
||||
DCONST_0
|
||||
DCMPL
|
||||
IFGE L5
|
||||
L11
|
||||
LINENUMBER 24 L11
|
||||
ALOAD 5
|
||||
ARETURN
|
||||
|
||||
"Optimistic" bytecode that requires invalidation on e.g overflow. Factor
|
||||
x2-3 speedup:
|
||||
|
||||
public static am3(Ljava/lang/Object;IILjava/lang/Object;III)I
|
||||
L0
|
||||
LINENUMBER 12 L0
|
||||
ALOAD 0
|
||||
INVOKEDYNAMIC dyn:getProp|getElem|getMethod:array(Ljava/lang/Object;)Ljava/lang/Object; [
|
||||
// handle kind 0x6 : INVOKESTATIC
|
||||
jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
|
||||
// arguments:
|
||||
0
|
||||
]
|
||||
ASTORE 8
|
||||
L1
|
||||
LINENUMBER 13 L1
|
||||
ALOAD 3
|
||||
INVOKEDYNAMIC dyn:getProp|getElem|getMethod:array(Ljava/lang/Object;)Ljava/lang/Object; [
|
||||
// handle kind 0x6 : INVOKESTATIC
|
||||
jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
|
||||
// arguments:
|
||||
0
|
||||
]
|
||||
ASTORE 9
|
||||
L2
|
||||
LINENUMBER 14 L2
|
||||
ILOAD 2
|
||||
SIPUSH 16383
|
||||
IAND
|
||||
ISTORE 10
|
||||
ILOAD 2
|
||||
BIPUSH 14
|
||||
ISHR
|
||||
ISTORE 11
|
||||
L3
|
||||
LINENUMBER 15 L3
|
||||
GOTO L4
|
||||
L5
|
||||
LINENUMBER 16 L5
|
||||
FRAME FULL [java/lang/Object I I java/lang/Object I I I T java/lang/Object java/lang/Object I I] []
|
||||
ALOAD 8
|
||||
ILOAD 1
|
||||
INVOKEDYNAMIC dyn:getElem|getProp|getMethod(Ljava/lang/Object;I)I [
|
||||
// handle kind 0x6 : INVOKESTATIC
|
||||
jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
|
||||
// arguments:
|
||||
0
|
||||
]
|
||||
SIPUSH 16383
|
||||
IAND
|
||||
ISTORE 12
|
||||
L6
|
||||
LINENUMBER 17 L6
|
||||
ALOAD 8
|
||||
ILOAD 1
|
||||
DUP
|
||||
ICONST_1
|
||||
IADD
|
||||
ISTORE 1
|
||||
INVOKEDYNAMIC dyn:getElem|getProp|getMethod(Ljava/lang/Object;I)I [
|
||||
// handle kind 0x6 : INVOKESTATIC
|
||||
jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
|
||||
// arguments:
|
||||
0
|
||||
]
|
||||
BIPUSH 14
|
||||
ISHR
|
||||
ISTORE 13
|
||||
L7
|
||||
LINENUMBER 18 L7
|
||||
ILOAD 11
|
||||
ILOAD 12
|
||||
BIPUSH 8
|
||||
INVOKESTATIC jdk/nashorn/internal/runtime/JSType.mulExact (III)I
|
||||
ILOAD 13
|
||||
ILOAD 10
|
||||
BIPUSH 9
|
||||
INVOKESTATIC jdk/nashorn/internal/runtime/JSType.mulExact (III)I
|
||||
IADD
|
||||
ISTORE 14
|
||||
L8
|
||||
LINENUMBER 19 L8
|
||||
ILOAD 10
|
||||
ILOAD 12
|
||||
BIPUSH 11
|
||||
INVOKESTATIC jdk/nashorn/internal/runtime/JSType.mulExact (III)I
|
||||
ILOAD 14
|
||||
SIPUSH 16383
|
||||
IAND
|
||||
BIPUSH 14
|
||||
ISHL
|
||||
IADD
|
||||
ALOAD 9
|
||||
ILOAD 4
|
||||
INVOKEDYNAMIC dyn:getElem|getProp|getMethod(Ljava/lang/Object;I)I [
|
||||
// handle kind 0x6 : INVOKESTATIC
|
||||
jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
|
||||
// arguments:
|
||||
0
|
||||
]
|
||||
IADD
|
||||
ILOAD 5
|
||||
IADD
|
||||
ISTORE 12
|
||||
L9
|
||||
LINENUMBER 20 L9
|
||||
ILOAD 12
|
||||
BIPUSH 28
|
||||
ISHR
|
||||
ILOAD 14
|
||||
BIPUSH 14
|
||||
ISHR
|
||||
IADD
|
||||
ILOAD 11
|
||||
ILOAD 13
|
||||
BIPUSH 21
|
||||
INVOKESTATIC jdk/nashorn/internal/runtime/JSType.mulExact (III)I
|
||||
IADD
|
||||
ISTORE 5
|
||||
L10
|
||||
LINENUMBER 21 L10
|
||||
ALOAD 9
|
||||
ILOAD 4
|
||||
DUP
|
||||
ICONST_1
|
||||
IADD
|
||||
ISTORE 4
|
||||
ILOAD 12
|
||||
LDC 268435455
|
||||
IAND
|
||||
INVOKEDYNAMIC dyn:setElem|setProp(Ljava/lang/Object;II)V [
|
||||
// handle kind 0x6 : INVOKESTATIC
|
||||
jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
|
||||
// arguments:
|
||||
0
|
||||
]
|
||||
L4
|
||||
FRAME SAME
|
||||
ILOAD 6
|
||||
ICONST_M1
|
||||
IADD
|
||||
DUP
|
||||
ISTORE 6
|
||||
ICONST_0
|
||||
IF_ICMPGE L5
|
||||
L11
|
||||
LINENUMBER 24 L11
|
||||
ILOAD 5
|
||||
IRETURN
|
||||
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.
|
||||
|
||||
|
||||
SYSTEM PROPERTY: -Dnashorn.codegen.debug, -Dnashorn.codegen.debug.trace=<x>
|
||||
SYSTEM PROPERTY: -Dnashorn.codegen.debug.trace=<x>
|
||||
|
||||
See the description of the codegen logger below.
|
||||
|
||||
|
||||
SYSTEM_PROPERTY: -Dnashorn.fields.debug
|
||||
SYSTEM PROPERTY: -Dnashorn.fields.objects
|
||||
|
||||
See the description on the fields logger below.
|
||||
When this property is true, Nashorn will only use object fields for
|
||||
AccessorProperties. This means that primitive values must be boxed
|
||||
when stored in a field, which is significantly slower than using
|
||||
primitive fields.
|
||||
|
||||
|
||||
SYSTEM PROPERTY: -Dnashorn.fields.dual
|
||||
|
||||
When this property is true, Nashorn will attempt to use primitive
|
||||
fields for AccessorProperties (currently just AccessorProperties, not
|
||||
spill properties). Memory footprint for script objects will increase,
|
||||
as we need to maintain both a primitive field (a long) as well as an
|
||||
Object field for the property value. Ints are represented as the 32
|
||||
low bits of the long fields. Doubles are represented as the
|
||||
doubleToLongBits of their value. This way a 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.
|
||||
|
||||
While dual fields in theory runs significantly faster than Object
|
||||
fields due to reduction of boxing and memory allocation overhead,
|
||||
there is still work to be done to make this a general purpose
|
||||
solution. Research is ongoing.
|
||||
By default, Nashorn uses dual object and long fields. Ints are
|
||||
represented as the 32 low bits of the long fields. Doubles are
|
||||
represented as the doubleToLongBits of their value. This way a
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
As long as only primitive values are written to the fields and enough
|
||||
type information exists to make sure that any reads don't have to be
|
||||
uselessly boxed and unboxed, this is significantly faster than the
|
||||
standard "Objects only" approach that currently is the default. See
|
||||
test/examples/dual-fields-micro.js for an example that runs twice as
|
||||
fast with dual fields as without them. Here, the compiler, can
|
||||
determine that we are dealing with numbers only throughout the entire
|
||||
property life span of the properties involved.
|
||||
|
||||
If a "real" object (not a boxed primitive) is written to a field that
|
||||
has a primitive representation, its callsite is relinked and an Object
|
||||
field is used forevermore for that particular field in that
|
||||
PropertyMap and its children, even if primitives are later assigned to
|
||||
it.
|
||||
|
||||
As the amount of compile time type information is very small in a
|
||||
dynamic language like JavaScript, it is frequently the case that
|
||||
something has to be treated as an object, because we don't know any
|
||||
better. In reality though, it is often a boxed primitive is stored to
|
||||
an AccessorProperty. The fastest way to handle this soundly is to use
|
||||
a callsite typecheck and avoid blowing the field up to an Object. We
|
||||
never revert object fields to primitives. Ping-pong:ing back and forth
|
||||
between primitive representation and Object representation would cause
|
||||
fatal performance overhead, so this is not an option.
|
||||
|
||||
For a general application the dual fields approach is still slower
|
||||
than objects only fields in some places, about the same in most cases,
|
||||
and significantly faster in very few. This is due the program using
|
||||
primitives, but we still can't prove it. For example "local_var a =
|
||||
call(); field = a;" may very well write a double to the field, but the
|
||||
compiler dare not guess a double type if field is a local variable,
|
||||
due to bytecode variables being strongly typed and later non
|
||||
interchangeable. To get around this, the entire method would have to
|
||||
be replaced and a continuation retained to restart from. We believe
|
||||
that the next steps we should go through are instead:
|
||||
|
||||
1) Implement method specialization based on callsite, as it's quite
|
||||
frequently the case that numbers are passed around, but currently our
|
||||
function nodes just have object types visible to the compiler. For
|
||||
example "var b = 17; func(a,b,17)" is an example where two parameters
|
||||
can be specialized, but the main version of func might also be called
|
||||
from another callsite with func(x,y,"string").
|
||||
|
||||
2) This requires lazy jitting as the functions have to be specialized
|
||||
per callsite.
|
||||
|
||||
Even though "function square(x) { return x*x }" might look like a
|
||||
trivial function that can always only take doubles, this is not
|
||||
true. Someone might have overridden the valueOf for x so that the
|
||||
toNumber coercion has side effects. To fulfil JavaScript semantics,
|
||||
the coercion has to run twice for both terms of the multiplication
|
||||
even if they are the same object. This means that call site
|
||||
specialization is necessary, not parameter specialization on the form
|
||||
"function square(x) { var xd = (double)x; return xd*xd; }", as one
|
||||
might first think.
|
||||
|
||||
Generating a method specialization for any variant of a function that
|
||||
we can determine by types at compile time is a combinatorial explosion
|
||||
of byte code (try it e.g. on all the variants of am3 in the Octane
|
||||
benchmark crypto.js). Thus, this needs to be lazy
|
||||
|
||||
3) Optimistic callsite writes, something on the form
|
||||
|
||||
x = y; //x is a field known to be a primitive. y is only an object as
|
||||
far as we can tell
|
||||
|
||||
turns into
|
||||
|
||||
try {
|
||||
x = (int)y;
|
||||
} catch (X is not an integer field right now | ClassCastException e) {
|
||||
x = y;
|
||||
}
|
||||
|
||||
Mini POC shows that this is the key to a lot of dual field performance
|
||||
in seemingly trivial micros where one unknown object, in reality
|
||||
actually a primitive, foils it for us. Very common pattern. Once we
|
||||
are "all primitives", dual fields runs a lot faster than Object fields
|
||||
only.
|
||||
|
||||
We still have to deal with objects vs primitives for local bytecode
|
||||
slots, possibly through code copying and versioning.
|
||||
|
||||
The Future:
|
||||
|
||||
We expect the usefulness of dual fields to increase significantly
|
||||
after the optimistic type system described in the section on
|
||||
integer arithmetic above is implemented.
|
||||
|
||||
|
||||
SYSTEM PROPERTY: -Dnashorn.compiler.symbol.trace=[<x>[,*]],
|
||||
-Dnashorn.compiler.symbol.stacktrace=[<x>[,*]]
|
||||
@ -628,6 +141,9 @@ for invoking a particular script function.
|
||||
"identical" - this method compares two script objects for reference
|
||||
equality. It is a == Java comparison
|
||||
|
||||
"equals" - Returns true if two objects are either referentially
|
||||
identical or equal as defined by java.lang.Object.equals.
|
||||
|
||||
"dumpCounters" - will dump the debug counters' current values to
|
||||
stdout.
|
||||
|
||||
@ -648,66 +164,66 @@ 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.
|
||||
|
||||
"getContext" - return the current Nashorn context.
|
||||
|
||||
SYSTEM PROPERTY: -Dnashorn.methodhandles.debug,
|
||||
-Dnashorn.methodhandles.debug=create
|
||||
"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.
|
||||
|
||||
If this property 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). This can be augmented with
|
||||
more information, for example, instance count, by subclassing or
|
||||
further extending the TraceMethodHandleFactory implementation in
|
||||
MethodHandleFactory.java.
|
||||
"diffPropertyMaps" Returns a diagnostic string representing the difference
|
||||
of two property maps.
|
||||
|
||||
If the property is specialized with "=create" as its option,
|
||||
instrumentation will be shown for method handles upon creation time
|
||||
rather than at runtime usage.
|
||||
"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.
|
||||
|
||||
"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.
|
||||
|
||||
|
||||
SYSTEM PROPERTY: -Dnashorn.methodhandles.debug.stacktrace
|
||||
|
||||
This does the same as nashorn.methodhandles.debug, but when enabled
|
||||
also dumps the stack trace for every instrumented method handle
|
||||
operation. Warning: This is enormously verbose, but provides a pretty
|
||||
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
|
||||
decent "grep:able" picture of where the calls are coming from.
|
||||
|
||||
See the description of the codegen logger below for a more verbose
|
||||
description of this option
|
||||
|
||||
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.scriptfunction.specialization.disable
|
||||
SYSTEM PROPERTY: -Dnashorn.spill.threshold=<x>
|
||||
|
||||
There are several "fast path" implementations of constructors and
|
||||
functions in the NativeObject classes that, in their original form,
|
||||
take a variable amount of arguments. Said functions are also declared
|
||||
to take Object parameters in their original form, as this is what the
|
||||
JavaScript specification mandates.
|
||||
However, we often know quite a lot more at a callsite of one of these
|
||||
functions. For example, Math.min is called with a fixed number (2) of
|
||||
integer arguments. The overhead of boxing these ints to Objects and
|
||||
folding them into an Object array for the generic varargs Math.min
|
||||
function is an order of magnitude slower than calling a specialized
|
||||
implementation of Math.min that takes two integers. Specialized
|
||||
functions and constructors are identified by the tag
|
||||
@SpecializedFunction and @SpecializedConstructor in the Nashorn
|
||||
code. The linker will link in the most appropriate (narrowest types,
|
||||
right number of types and least number of arguments) specialization if
|
||||
specializations are available.
|
||||
|
||||
Every ScriptFunction may carry specializations that the linker can
|
||||
choose from. This framework will likely be extended for user defined
|
||||
functions. The compiler can often infer enough parameter type info
|
||||
from callsites for in order to generate simpler versions with less
|
||||
generic Object types. This feature depends on future lazy jitting, as
|
||||
there tend to be many calls to user defined functions, some where the
|
||||
callsite can be specialized, some where we mostly see object
|
||||
parameters even at the callsite.
|
||||
|
||||
If this system property is set to true, the linker will not attempt to
|
||||
use any specialized function or constructor for native objects, but
|
||||
just call the generic one.
|
||||
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.
|
||||
|
||||
|
||||
SYSTEM PROPERTY: -Dnashorn.tcs.miss.samplePercent=<x>
|
||||
@ -719,8 +235,47 @@ 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.
|
||||
|
||||
SYSTEM PROPERTY: -Dnashorn.persistent.code.cache
|
||||
|
||||
SYSTEM_PROPERTY: -Dnashorn.profilefile=<filename>
|
||||
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".
|
||||
|
||||
|
||||
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>
|
||||
|
||||
When running with the profile callsite options (-pcs), Nashorn will
|
||||
dump profiling data for all callsites to stderr as a shutdown hook. To
|
||||
@ -736,6 +291,11 @@ JDK's java.util.regex package. Set this property to "joni" to install
|
||||
an implementation based on Joni, the regular expression engine used by
|
||||
the JRuby project. The default value for this flag is "joni"
|
||||
|
||||
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.
|
||||
|
||||
===============
|
||||
2. The loggers.
|
||||
@ -767,7 +327,9 @@ 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
|
||||
|
||||
The subsystems that currently support logging are:
|
||||
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.
|
||||
|
||||
|
||||
* compiler
|
||||
@ -780,6 +342,14 @@ settings that all the tiers of codegen (e.g. Lower and CodeGenerator)
|
||||
use.s
|
||||
|
||||
|
||||
* 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.
|
||||
|
||||
|
||||
* codegen
|
||||
|
||||
The code generator is the emitter stage of the code pipeline, and
|
||||
@ -836,25 +406,13 @@ and inlining finally blocks.
|
||||
Lower is also responsible for determining control flow information
|
||||
like end points.
|
||||
|
||||
* symbols
|
||||
|
||||
* attr
|
||||
The symbols logger tracks the assignment os symbols to identifiers.
|
||||
|
||||
The lowering annotates a FunctionNode with symbols for each identifier
|
||||
and transforms high level constructs into lower level ones, that the
|
||||
CodeGenerator consumes.
|
||||
|
||||
Lower logging typically outputs things like post pass actions,
|
||||
insertions of casts because symbol types have been changed and type
|
||||
specialization information. Currently very little info is generated by
|
||||
this logger. This will probably change.
|
||||
|
||||
|
||||
* finalize
|
||||
|
||||
This --log=finalize log option outputs information for type finalization,
|
||||
the third tier of the compiler. This means things like placement of
|
||||
specialized scope nodes or explicit conversions.
|
||||
* scopedepths
|
||||
|
||||
This logs the calculation of scope depths for non-local symbols.
|
||||
|
||||
* fields
|
||||
|
||||
@ -896,6 +454,21 @@ Here is an example:
|
||||
[time]
|
||||
[time] Total runtime: 11994 ms (Non-runtime: 11027 ms [91%])
|
||||
|
||||
* 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.
|
||||
|
||||
=======================
|
||||
3. Undocumented options
|
||||
=======================
|
||||
|
||||
@ -48,7 +48,7 @@ import jdk.nashorn.internal.runtime.options.Options;
|
||||
/**
|
||||
* This class is abstraction for all method handle, switchpoint and method type
|
||||
* operations. This enables the functionality interface to be subclassed and
|
||||
* intrumensted, as it has been proven vital to keep the number of method
|
||||
* instrumented, as it has been proven vital to keep the number of method
|
||||
* handles in the system down.
|
||||
*
|
||||
* All operations of the above type should go through this class, and not
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user