Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell11
提交
333ac25a
D
dragonwell11
项目概览
openanolis
/
dragonwell11
通知
7
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell11
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
333ac25a
编写于
10月 30, 2014
作者:
H
hannesw
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8062401: User accessors require boxing and do not support optimistic types
Reviewed-by: jlaskey, lagergren
上级
81a80707
变更
12
隐藏空白更改
内联
并排
Showing
12 changed file
with
289 addition
and
131 deletion
+289
-131
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SpillObjectCreator.java
...sses/jdk/nashorn/internal/codegen/SpillObjectCreator.java
+1
-1
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java
...e/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java
+1
-1
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java
...re/classes/jdk/nashorn/internal/objects/NativeObject.java
+1
-1
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AccessorProperty.java
...lasses/jdk/nashorn/internal/runtime/AccessorProperty.java
+19
-37
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FindProperty.java
...re/classes/jdk/nashorn/internal/runtime/FindProperty.java
+8
-2
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java
.../share/classes/jdk/nashorn/internal/runtime/Property.java
+37
-10
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java
...are/classes/jdk/nashorn/internal/runtime/PropertyMap.java
+1
-1
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java
...re/classes/jdk/nashorn/internal/runtime/ScriptObject.java
+1
-1
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/SpillProperty.java
...e/classes/jdk/nashorn/internal/runtime/SpillProperty.java
+2
-2
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/UserAccessorProperty.java
...es/jdk/nashorn/internal/runtime/UserAccessorProperty.java
+123
-75
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java
...lasses/jdk/nashorn/internal/runtime/linker/Bootstrap.java
+14
-0
nashorn/test/examples/getter-setter-micro.js
nashorn/test/examples/getter-setter-micro.js
+81
-0
未找到文件。
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SpillObjectCreator.java
浏览文件 @
333ac25a
...
...
@@ -88,7 +88,7 @@ public final class SpillObjectCreator extends ObjectCreator<Expression> {
final
Property
property
=
propertyMap
.
findProperty
(
key
);
if
(
property
!=
null
)
{
// normal property key
property
.
set
Current
Type
(
JSType
.
unboxedFieldType
(
constantValue
));
property
.
setType
(
JSType
.
unboxedFieldType
(
constantValue
));
final
int
slot
=
property
.
getSlot
();
if
(!
OBJECT_FIELDS_ONLY
&&
constantValue
instanceof
Number
)
{
jpresetValues
[
slot
]
=
ObjectClassGenerator
.
pack
((
Number
)
constantValue
);
...
...
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java
浏览文件 @
333ac25a
...
...
@@ -117,7 +117,7 @@ final class TypeEvaluator {
}
final
Property
property
=
find
.
getProperty
();
final
Class
<?>
propertyClass
=
property
.
get
Current
Type
();
final
Class
<?>
propertyClass
=
property
.
getType
();
if
(
propertyClass
==
null
)
{
// propertyClass == null means its value is Undefined. It is probably not initialized yet, so we won't make
// a type assumption yet.
...
...
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java
浏览文件 @
333ac25a
...
...
@@ -672,7 +672,7 @@ public final class NativeObject {
for
(
final
Property
prop
:
properties
)
{
if
(
prop
.
isEnumerable
())
{
final
Object
value
=
sourceObj
.
get
(
prop
.
getKey
());
prop
.
set
Current
Type
(
Object
.
class
);
prop
.
setType
(
Object
.
class
);
prop
.
setValue
(
sourceObj
,
sourceObj
,
value
,
false
);
propList
.
add
(
prop
);
}
...
...
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AccessorProperty.java
浏览文件 @
333ac25a
...
...
@@ -144,13 +144,6 @@ public class AccessorProperty extends Property {
/** Seed setter for the Object version of this field */
transient
MethodHandle
objectSetter
;
/**
* Current type of this object, in object only mode, this is an Object.class. In dual-fields mode
* null means undefined, and primitive types are allowed. The reason a special type is used for
* undefined, is that are no bits left to represent it in primitive types
*/
private
Class
<?>
currentType
;
/**
* Delegate constructor for bound properties. This is used for properties created by
* {@link ScriptRuntime#mergeScope} and the Nashorn {@code Object.bindProperties} method.
...
...
@@ -171,7 +164,7 @@ public class AccessorProperty extends Property {
this
.
objectSetter
=
bindTo
(
property
.
objectSetter
,
delegate
);
property
.
GETTER_CACHE
=
new
MethodHandle
[
NOOF_TYPES
];
// Properties created this way are bound to a delegate
set
CurrentType
(
property
.
getCurren
tType
());
set
Type
(
property
.
ge
tType
());
}
/**
...
...
@@ -248,7 +241,7 @@ public class AccessorProperty extends Property {
objectGetter
=
getter
.
type
()
!=
Lookup
.
GET_OBJECT_TYPE
?
MH
.
asType
(
getter
,
Lookup
.
GET_OBJECT_TYPE
)
:
getter
;
objectSetter
=
setter
!=
null
&&
setter
.
type
()
!=
Lookup
.
SET_OBJECT_TYPE
?
MH
.
asType
(
setter
,
Lookup
.
SET_OBJECT_TYPE
)
:
setter
;
set
Current
Type
(
OBJECT_FIELDS_ONLY
?
Object
.
class
:
getterType
);
setType
(
OBJECT_FIELDS_ONLY
?
Object
.
class
:
getterType
);
}
/**
...
...
@@ -317,7 +310,7 @@ public class AccessorProperty extends Property {
*/
public
AccessorProperty
(
final
String
key
,
final
int
flags
,
final
Class
<?>
structure
,
final
int
slot
,
final
Class
<?>
initialType
)
{
this
(
key
,
flags
,
structure
,
slot
);
set
Current
Type
(
OBJECT_FIELDS_ONLY
?
Object
.
class
:
initialType
);
setType
(
OBJECT_FIELDS_ONLY
?
Object
.
class
:
initialType
);
}
/**
...
...
@@ -330,13 +323,13 @@ public class AccessorProperty extends Property {
protected
AccessorProperty
(
final
AccessorProperty
property
,
final
Class
<?>
newType
)
{
super
(
property
,
property
.
getFlags
());
this
.
GETTER_CACHE
=
newType
!=
property
.
get
Current
Type
()
?
new
MethodHandle
[
NOOF_TYPES
]
:
property
.
GETTER_CACHE
;
this
.
GETTER_CACHE
=
newType
!=
property
.
get
Local
Type
()
?
new
MethodHandle
[
NOOF_TYPES
]
:
property
.
GETTER_CACHE
;
this
.
primitiveGetter
=
property
.
primitiveGetter
;
this
.
primitiveSetter
=
property
.
primitiveSetter
;
this
.
objectGetter
=
property
.
objectGetter
;
this
.
objectSetter
=
property
.
objectSetter
;
set
Current
Type
(
newType
);
setType
(
newType
);
}
/**
...
...
@@ -345,7 +338,7 @@ public class AccessorProperty extends Property {
* @param property source property
*/
protected
AccessorProperty
(
final
AccessorProperty
property
)
{
this
(
property
,
property
.
get
Current
Type
());
this
(
property
,
property
.
get
Local
Type
());
}
/**
...
...
@@ -354,7 +347,7 @@ public class AccessorProperty extends Property {
* @param initialValue initial value
*/
protected
final
void
setInitialValue
(
final
ScriptObject
owner
,
final
Object
initialValue
)
{
set
Current
Type
(
JSType
.
unboxedFieldType
(
initialValue
));
setType
(
JSType
.
unboxedFieldType
(
initialValue
));
if
(
initialValue
instanceof
Integer
)
{
invokeSetter
(
owner
,
((
Integer
)
initialValue
).
intValue
());
}
else
if
(
initialValue
instanceof
Long
)
{
...
...
@@ -370,7 +363,7 @@ public class AccessorProperty extends Property {
* Initialize the type of a property
*/
protected
final
void
initializeType
()
{
set
Current
Type
(
OBJECT_FIELDS_ONLY
?
Object
.
class
:
null
);
setType
(
OBJECT_FIELDS_ONLY
?
Object
.
class
:
null
);
}
private
void
readObject
(
final
ObjectInputStream
s
)
throws
IOException
,
ClassNotFoundException
{
...
...
@@ -557,12 +550,12 @@ public class AccessorProperty extends Property {
}
else
{
getter
=
debug
(
createGetter
(
get
Current
Type
(),
get
Local
Type
(),
type
,
primitiveGetter
,
objectGetter
,
INVALID_PROGRAM_POINT
),
get
Current
Type
(),
get
Local
Type
(),
type
,
"get"
);
getterCache
[
i
]
=
getter
;
...
...
@@ -582,18 +575,18 @@ public class AccessorProperty extends Property {
return
debug
(
createGetter
(
get
Current
Type
(),
get
Local
Type
(),
type
,
primitiveGetter
,
objectGetter
,
programPoint
),
get
Current
Type
(),
get
Local
Type
(),
type
,
"get"
);
}
private
MethodHandle
getOptimisticPrimitiveGetter
(
final
Class
<?>
type
,
final
int
programPoint
)
{
final
MethodHandle
g
=
getGetter
(
get
Current
Type
());
final
MethodHandle
g
=
getGetter
(
get
Local
Type
());
return
MH
.
asType
(
OptimisticReturnFilters
.
filterOptimisticReturnValue
(
g
,
type
,
programPoint
),
g
.
type
().
changeReturnType
(
type
));
}
...
...
@@ -631,7 +624,7 @@ public class AccessorProperty extends Property {
}
private
MethodHandle
generateSetter
(
final
Class
<?>
forType
,
final
Class
<?>
type
)
{
return
debug
(
createSetter
(
forType
,
type
,
primitiveSetter
,
objectSetter
),
get
Current
Type
(),
type
,
"set"
);
return
debug
(
createSetter
(
forType
,
type
,
primitiveSetter
,
objectSetter
),
get
Local
Type
(),
type
,
"set"
);
}
/**
...
...
@@ -639,7 +632,7 @@ public class AccessorProperty extends Property {
* @return true if undefined
*/
protected
final
boolean
isUndefined
()
{
return
get
Current
Type
()
==
null
;
return
get
Local
Type
()
==
null
;
}
@Override
...
...
@@ -647,7 +640,7 @@ public class AccessorProperty extends Property {
checkUndeclared
();
final
int
typeIndex
=
getAccessorTypeIndex
(
type
);
final
int
currentTypeIndex
=
getAccessorTypeIndex
(
get
Current
Type
());
final
int
currentTypeIndex
=
getAccessorTypeIndex
(
get
Local
Type
());
//if we are asking for an object setter, but are still a primitive type, we might try to box it
MethodHandle
mh
;
...
...
@@ -656,13 +649,13 @@ public class AccessorProperty extends Property {
final
PropertyMap
newMap
=
getWiderMap
(
currentMap
,
newProperty
);
final
MethodHandle
widerSetter
=
newProperty
.
getSetter
(
type
,
newMap
);
final
Class
<?>
ct
=
get
Current
Type
();
final
Class
<?>
ct
=
get
Local
Type
();
mh
=
MH
.
filterArguments
(
widerSetter
,
0
,
MH
.
insertArguments
(
debugReplace
(
ct
,
type
,
currentMap
,
newMap
)
,
1
,
newMap
));
if
(
ct
!=
null
&&
ct
.
isPrimitive
()
&&
!
type
.
isPrimitive
())
{
mh
=
ObjectClassGenerator
.
createGuardBoxedPrimitiveSetter
(
ct
,
generateSetter
(
ct
,
ct
),
mh
);
}
}
else
{
final
Class
<?>
forType
=
isUndefined
()
?
type
:
get
Current
Type
();
final
Class
<?>
forType
=
isUndefined
()
?
type
:
get
Local
Type
();
mh
=
generateSetter
(!
forType
.
isPrimitive
()
?
Object
.
class
:
forType
,
type
);
}
...
...
@@ -681,24 +674,13 @@ public class AccessorProperty extends Property {
return
false
;
}
// Return true for currently undefined even if non-writable/configurable to allow initialization of ES6 CONST.
return
get
CurrentType
()
==
null
||
(
getCurrent
Type
()
!=
Object
.
class
&&
(
isConfigurable
()
||
isWritable
()));
return
get
LocalType
()
==
null
||
(
getLocal
Type
()
!=
Object
.
class
&&
(
isConfigurable
()
||
isWritable
()));
}
private
boolean
needsInvalidator
(
final
int
typeIndex
,
final
int
currentTypeIndex
)
{
return
canChangeType
()
&&
typeIndex
>
currentTypeIndex
;
}
@Override
public
final
void
setCurrentType
(
final
Class
<?>
currentType
)
{
assert
currentType
!=
boolean
.
class
:
"no boolean storage support yet - fix this"
;
this
.
currentType
=
currentType
==
null
?
null
:
currentType
.
isPrimitive
()
?
currentType
:
Object
.
class
;
}
@Override
public
Class
<?>
getCurrentType
()
{
return
currentType
;
}
private
MethodHandle
debug
(
final
MethodHandle
mh
,
final
Class
<?>
forType
,
final
Class
<?>
type
,
final
String
tag
)
{
if
(!
Context
.
DEBUG
||
!
Global
.
hasInstance
())
{
return
mh
;
...
...
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FindProperty.java
浏览文件 @
333ac25a
...
...
@@ -84,13 +84,18 @@ public final class FindProperty {
* @return method handle for the getter
*/
public
MethodHandle
getGetter
(
final
Class
<?>
type
,
final
int
programPoint
,
final
LinkRequest
request
)
{
final
MethodHandle
getter
;
MethodHandle
getter
;
if
(
isValid
(
programPoint
))
{
getter
=
property
.
getOptimisticGetter
(
type
,
programPoint
);
}
else
{
getter
=
property
.
getGetter
(
type
);
}
if
(
property
instanceof
UserAccessorProperty
)
{
getter
=
MH
.
insertArguments
(
getter
,
1
,
UserAccessorProperty
.
getINVOKE_UA_GETTER
(
type
,
programPoint
));
if
(
isValid
(
programPoint
)
&&
type
.
isPrimitive
())
{
getter
=
MH
.
insertArguments
(
getter
,
1
,
programPoint
);
}
property
.
setType
(
type
);
return
insertAccessorsGetter
((
UserAccessorProperty
)
property
,
request
,
getter
);
}
return
getter
;
...
...
@@ -111,7 +116,8 @@ public final class FindProperty {
public
MethodHandle
getSetter
(
final
Class
<?>
type
,
final
boolean
strict
,
final
LinkRequest
request
)
{
MethodHandle
setter
=
property
.
getSetter
(
type
,
getOwner
().
getMap
());
if
(
property
instanceof
UserAccessorProperty
)
{
setter
=
MH
.
insertArguments
(
setter
,
1
,
strict
?
property
.
getKey
()
:
null
);
setter
=
MH
.
insertArguments
(
setter
,
1
,
UserAccessorProperty
.
getINVOKE_UA_SETTER
(
type
),
strict
?
property
.
getKey
()
:
null
);
property
.
setType
(
type
);
return
insertAccessorsGetter
((
UserAccessorProperty
)
property
,
request
,
setter
);
}
...
...
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java
浏览文件 @
333ac25a
...
...
@@ -102,6 +102,13 @@ public abstract class Property implements Serializable {
/** Property field number or spill slot. */
private
final
int
slot
;
/**
* Current type of this object, in object only mode, this is an Object.class. In dual-fields mode
* null means undefined, and primitive types are allowed. The reason a special type is used for
* undefined, is that are no bits left to represent it in primitive types
*/
private
Class
<?>
type
;
/** SwitchPoint that is invalidated when property is changed, optional */
protected
transient
SwitchPoint
builtinSwitchPoint
;
...
...
@@ -536,7 +543,7 @@ public abstract class Property implements Serializable {
* <p>
* see {@link ObjectClassGenerator#createSetter(Class, Class, MethodHandle, MethodHandle)}
* if you are interested in the internal details of this. Note that if you
* are running
in default mode, with {@code -Dnashorn.fields.dual=true}, disabled
, the setters
* are running
with {@code -Dnashorn.fields.objects=true}
, the setters
* will currently never change, as all properties are represented as Object field,
* the Object fields are Initialized to {@code ScriptRuntime.UNDEFINED} and primitives are
* boxed/unboxed upon every access, which is not necessarily optimal
...
...
@@ -569,7 +576,7 @@ public abstract class Property implements Serializable {
@Override
public
int
hashCode
()
{
final
Class
<?>
type
=
get
Current
Type
();
final
Class
<?>
type
=
get
Local
Type
();
return
Objects
.
hashCode
(
this
.
key
)
^
flags
^
getSlot
()
^
(
type
==
null
?
0
:
type
.
hashCode
());
}
...
...
@@ -586,7 +593,7 @@ public abstract class Property implements Serializable {
final
Property
otherProperty
=
(
Property
)
other
;
return
equalsWithoutType
(
otherProperty
)
&&
getCurrentType
()
==
otherProperty
.
getCurrent
Type
();
getLocalType
()
==
otherProperty
.
getLocal
Type
();
}
boolean
equalsWithoutType
(
final
Property
otherProperty
)
{
...
...
@@ -615,7 +622,7 @@ public abstract class Property implements Serializable {
*/
public
final
String
toStringShort
()
{
final
StringBuilder
sb
=
new
StringBuilder
();
final
Class
<?>
type
=
get
Current
Type
();
final
Class
<?>
type
=
get
Local
Type
();
sb
.
append
(
getKey
()).
append
(
" ("
).
append
(
type
(
type
)).
append
(
')'
);
return
sb
.
toString
();
}
...
...
@@ -632,7 +639,7 @@ public abstract class Property implements Serializable {
@Override
public
String
toString
()
{
final
StringBuilder
sb
=
new
StringBuilder
();
final
Class
<?>
type
=
get
Current
Type
();
final
Class
<?>
type
=
get
Local
Type
();
sb
.
append
(
indent
(
getKey
(),
20
)).
append
(
" id="
).
...
...
@@ -656,20 +663,40 @@ public abstract class Property implements Serializable {
}
/**
* Get the current type of this
field. If you are not running with dual
fields enabled,
* Get the current type of this
property. If you are running with object
fields enabled,
* this will always be Object.class. See the value representation explanation in
* {@link Property#getSetter(Class, PropertyMap)} and {@link ObjectClassGenerator}
* for more information.
*
* <p>Note that for user accessor properties, this returns the type of the last observed
* value passed to or returned by a user accessor. Use {@link #getLocalType()} to always get
* the type of the actual value stored in the property slot.</p>
*
* @return current type of property, null means undefined
*/
public
abstract
Class
<?>
getCurrentType
();
public
final
Class
<?>
getType
()
{
return
type
;
}
/**
*
Reset the current type of this property
* @param
currentType new current
type
*
Set the type of this property.
* @param
type new
type
*/
public
abstract
void
setCurrentType
(
final
Class
<?>
currentType
);
public
final
void
setType
(
final
Class
<?>
type
)
{
assert
type
!=
boolean
.
class
:
"no boolean storage support yet - fix this"
;
this
.
type
=
type
==
null
?
null
:
type
.
isPrimitive
()
?
type
:
Object
.
class
;
}
/**
* Get the type of the value in the local property slot. This returns the same as
* {@link #getType()} for normal properties, but always returns {@code Object.class}
* for {@link UserAccessorProperty}s as their local type is a pair of accessor references.
*
* @return the local property type
*/
protected
Class
<?>
getLocalType
()
{
return
getType
();
}
/**
* Check whether this Property can ever change its type. The default is false, and if
...
...
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java
浏览文件 @
333ac25a
...
...
@@ -512,7 +512,7 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
assert
sameType
||
oldProperty
instanceof
AccessorProperty
&&
newProperty
instanceof
UserAccessorProperty
:
"arbitrary replaceProperty attempted "
+
sameType
+
" oldProperty="
+
oldProperty
.
getClass
()
+
" newProperty="
+
newProperty
.
getClass
()
+
" ["
+
oldProperty
.
get
CurrentType
()
+
" => "
+
newProperty
.
getCurrent
Type
()
+
"]"
;
"arbitrary replaceProperty attempted "
+
sameType
+
" oldProperty="
+
oldProperty
.
getClass
()
+
" newProperty="
+
newProperty
.
getClass
()
+
" ["
+
oldProperty
.
get
LocalType
()
+
" => "
+
newProperty
.
getLocal
Type
()
+
"]"
;
newMap
.
flags
=
flags
;
...
...
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java
浏览文件 @
333ac25a
...
...
@@ -969,7 +969,7 @@ public abstract class ScriptObject implements PropertyAccess {
final
UserAccessorProperty
uc
=
(
UserAccessorProperty
)
oldProperty
;
final
int
slot
=
uc
.
getSlot
();
assert
uc
.
get
Current
Type
()
==
Object
.
class
;
assert
uc
.
get
Local
Type
()
==
Object
.
class
;
if
(
slot
>=
spillLength
)
{
uc
.
setAccessors
(
this
,
getMap
(),
new
UserAccessorProperty
.
Accessors
(
getter
,
setter
));
}
else
{
...
...
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/SpillProperty.java
浏览文件 @
333ac25a
...
...
@@ -161,12 +161,12 @@ public class SpillProperty extends AccessorProperty {
*/
public
SpillProperty
(
final
String
key
,
final
int
flags
,
final
int
slot
)
{
super
(
key
,
flags
,
slot
,
primitiveGetter
(
slot
),
primitiveSetter
(
slot
),
objectGetter
(
slot
),
objectSetter
(
slot
));
assert
!
OBJECT_FIELDS_ONLY
||
get
Current
Type
()
==
Object
.
class
;
assert
!
OBJECT_FIELDS_ONLY
||
get
Local
Type
()
==
Object
.
class
;
}
SpillProperty
(
final
String
key
,
final
int
flags
,
final
int
slot
,
final
Class
<?>
initialType
)
{
this
(
key
,
flags
,
slot
);
set
Current
Type
(
OBJECT_FIELDS_ONLY
?
Object
.
class
:
initialType
);
setType
(
OBJECT_FIELDS_ONLY
?
Object
.
class
:
initialType
);
}
SpillProperty
(
final
String
key
,
final
int
flags
,
final
int
slot
,
final
ScriptObject
owner
,
final
Object
initialValue
)
{
...
...
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/UserAccessorProperty.java
浏览文件 @
333ac25a
...
...
@@ -27,16 +27,16 @@ package jdk.nashorn.internal.runtime;
import
static
jdk
.
nashorn
.
internal
.
lookup
.
Lookup
.
MH
;
import
static
jdk
.
nashorn
.
internal
.
runtime
.
ECMAErrors
.
typeError
;
import
static
jdk
.
nashorn
.
internal
.
runtime
.
JSType
.
CONVERT_OBJECT_OPTIMISTIC
;
import
static
jdk
.
nashorn
.
internal
.
runtime
.
JSType
.
getAccessorTypeIndex
;
import
static
jdk
.
nashorn
.
internal
.
runtime
.
ScriptRuntime
.
UNDEFINED
;
import
static
jdk
.
nashorn
.
internal
.
runtime
.
UnwarrantedOptimismException
.
INVALID_PROGRAM_POINT
;
import
static
jdk
.
nashorn
.
internal
.
runtime
.
linker
.
NashornCallSiteDescriptor
.
CALLSITE_PROGRAM_POINT_SHIFT
;
import
java.lang.invoke.MethodHandle
;
import
java.lang.invoke.MethodHandles
;
import
java.lang.invoke.MethodType
;
import
java.util.concurrent.Callable
;
import
jdk.nashorn.internal.lookup.Lookup
;
import
jdk.nashorn.internal.runtime.linker.Bootstrap
;
import
jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor
;
/**
* Property with user defined getters/setters. Actual getter and setter
...
...
@@ -69,38 +69,29 @@ public final class UserAccessorProperty extends SpillProperty {
private
static
final
MethodHandles
.
Lookup
LOOKUP
=
MethodHandles
.
lookup
();
/** Getter method handle */
private
final
static
MethodHandle
INVOKE_GETTER_ACCESSOR
=
findOwnMH_S
(
"invokeGetterAccessor"
,
Object
.
class
,
Accessors
.
class
,
Object
.
class
);
private
final
static
MethodHandle
INVOKE_OBJECT_GETTER
=
findOwnMH_S
(
"invokeObjectGetter"
,
Object
.
class
,
Accessors
.
class
,
MethodHandle
.
class
,
Object
.
class
);
private
final
static
MethodHandle
INVOKE_INT_GETTER
=
findOwnMH_S
(
"invokeIntGetter"
,
int
.
class
,
Accessors
.
class
,
MethodHandle
.
class
,
int
.
class
,
Object
.
class
);
private
final
static
MethodHandle
INVOKE_LONG_GETTER
=
findOwnMH_S
(
"invokeLongGetter"
,
long
.
class
,
Accessors
.
class
,
MethodHandle
.
class
,
int
.
class
,
Object
.
class
);
private
final
static
MethodHandle
INVOKE_NUMBER_GETTER
=
findOwnMH_S
(
"invokeNumberGetter"
,
double
.
class
,
Accessors
.
class
,
MethodHandle
.
class
,
int
.
class
,
Object
.
class
);
/** Setter method handle */
private
final
static
MethodHandle
INVOKE_SETTER_ACCESSOR
=
findOwnMH_S
(
"invokeSetterAccessor"
,
void
.
class
,
Accessors
.
class
,
String
.
class
,
Object
.
class
,
Object
.
class
);
/** Dynamic invoker for getter */
private
static
final
Object
GETTER_INVOKER_KEY
=
new
Object
();
private
static
MethodHandle
getINVOKE_UA_GETTER
()
{
return
Context
.
getGlobal
().
getDynamicInvoker
(
GETTER_INVOKER_KEY
,
new
Callable
<
MethodHandle
>()
{
@Override
public
MethodHandle
call
()
{
return
Bootstrap
.
createDynamicInvoker
(
"dyn:call"
,
Object
.
class
,
Object
.
class
,
Object
.
class
);
}
});
private
final
static
MethodHandle
INVOKE_OBJECT_SETTER
=
findOwnMH_S
(
"invokeObjectSetter"
,
void
.
class
,
Accessors
.
class
,
MethodHandle
.
class
,
String
.
class
,
Object
.
class
,
Object
.
class
);
private
final
static
MethodHandle
INVOKE_INT_SETTER
=
findOwnMH_S
(
"invokeIntSetter"
,
void
.
class
,
Accessors
.
class
,
MethodHandle
.
class
,
String
.
class
,
Object
.
class
,
int
.
class
);
private
final
static
MethodHandle
INVOKE_LONG_SETTER
=
findOwnMH_S
(
"invokeLongSetter"
,
void
.
class
,
Accessors
.
class
,
MethodHandle
.
class
,
String
.
class
,
Object
.
class
,
long
.
class
);
private
final
static
MethodHandle
INVOKE_NUMBER_SETTER
=
findOwnMH_S
(
"invokeNumberSetter"
,
void
.
class
,
Accessors
.
class
,
MethodHandle
.
class
,
String
.
class
,
Object
.
class
,
double
.
class
);
static
MethodHandle
getINVOKE_UA_GETTER
(
final
Class
<?>
returnType
,
final
int
programPoint
)
{
if
(
UnwarrantedOptimismException
.
isValid
(
programPoint
))
{
final
int
flags
=
NashornCallSiteDescriptor
.
CALLSITE_OPTIMISTIC
|
programPoint
<<
CALLSITE_PROGRAM_POINT_SHIFT
;
return
Bootstrap
.
createDynamicInvoker
(
"dyn:call"
,
flags
,
returnType
,
Object
.
class
,
Object
.
class
);
}
else
{
return
Bootstrap
.
createDynamicInvoker
(
"dyn:call"
,
Object
.
class
,
Object
.
class
,
Object
.
class
);
}
}
/** Dynamic invoker for setter */
private
static
Object
SETTER_INVOKER_KEY
=
new
Object
();
private
static
MethodHandle
getINVOKE_UA_SETTER
()
{
return
Context
.
getGlobal
().
getDynamicInvoker
(
SETTER_INVOKER_KEY
,
new
Callable
<
MethodHandle
>()
{
@Override
public
MethodHandle
call
()
{
return
Bootstrap
.
createDynamicInvoker
(
"dyn:call"
,
void
.
class
,
Object
.
class
,
Object
.
class
,
Object
.
class
);
}
});
static
MethodHandle
getINVOKE_UA_SETTER
(
final
Class
<?>
valueType
)
{
return
Bootstrap
.
createDynamicInvoker
(
"dyn:call"
,
void
.
class
,
Object
.
class
,
Object
.
class
,
valueType
);
}
/**
...
...
@@ -158,7 +149,7 @@ public final class UserAccessorProperty extends SpillProperty {
}
@Override
p
ublic
Class
<?>
getCurrent
Type
()
{
p
rotected
Class
<?>
getLocal
Type
()
{
return
Object
.
class
;
}
...
...
@@ -189,7 +180,13 @@ public final class UserAccessorProperty extends SpillProperty {
@Override
public
Object
getObjectValue
(
final
ScriptObject
self
,
final
ScriptObject
owner
)
{
return
invokeGetterAccessor
(
getAccessors
((
owner
!=
null
)
?
owner
:
self
),
self
);
try
{
return
invokeObjectGetter
(
getAccessors
((
owner
!=
null
)
?
owner
:
self
),
getINVOKE_UA_GETTER
(
Object
.
class
,
INVALID_PROGRAM_POINT
),
self
);
}
catch
(
final
Error
|
RuntimeException
t
)
{
throw
t
;
}
catch
(
final
Throwable
t
)
{
throw
new
RuntimeException
(
t
);
}
}
@Override
...
...
@@ -209,41 +206,33 @@ public final class UserAccessorProperty extends SpillProperty {
@Override
public
void
setValue
(
final
ScriptObject
self
,
final
ScriptObject
owner
,
final
Object
value
,
final
boolean
strict
)
{
invokeSetterAccessor
(
getAccessors
((
owner
!=
null
)
?
owner
:
self
),
strict
?
getKey
()
:
null
,
self
,
value
);
try
{
invokeObjectSetter
(
getAccessors
((
owner
!=
null
)
?
owner
:
self
),
getINVOKE_UA_SETTER
(
Object
.
class
),
strict
?
getKey
()
:
null
,
self
,
value
);
}
catch
(
final
Error
|
RuntimeException
t
)
{
throw
t
;
}
catch
(
final
Throwable
t
)
{
throw
new
RuntimeException
(
t
);
}
}
@Override
public
MethodHandle
getGetter
(
final
Class
<?>
type
)
{
//this returns a getter on the format (Accessors, Object receiver)
return
Lookup
.
filterReturnType
(
INVOKE_
GETTER_ACCESSO
R
,
type
);
return
Lookup
.
filterReturnType
(
INVOKE_
OBJECT_GETTE
R
,
type
);
}
@Override
public
MethodHandle
getOptimisticGetter
(
final
Class
<?>
type
,
final
int
programPoint
)
{
//fortype is always object, but in the optimistic world we have to throw
//unwarranted optimism exception for narrower types. We can improve this
//by checking for boxed types and unboxing them, but it is doubtful that
//this gives us any performance, as UserAccessorProperties are typically not
//primitives. Are there? TODO: investigate later. For now we just throw an
//exception for narrower types than object
if
(
type
.
isPrimitive
())
{
final
MethodHandle
getter
=
getGetter
(
Object
.
class
);
final
MethodHandle
mh
=
MH
.
asType
(
MH
.
filterReturnValue
(
getter
,
MH
.
insertArguments
(
CONVERT_OBJECT_OPTIMISTIC
.
get
(
getAccessorTypeIndex
(
type
)),
1
,
programPoint
)),
getter
.
type
().
changeReturnType
(
type
));
return
mh
;
if
(
type
==
int
.
class
)
{
return
INVOKE_INT_GETTER
;
}
else
if
(
type
==
long
.
class
)
{
return
INVOKE_LONG_GETTER
;
}
else
if
(
type
==
double
.
class
)
{
return
INVOKE_NUMBER_GETTER
;
}
else
{
assert
type
==
Object
.
class
;
return
INVOKE_OBJECT_GETTER
;
}
assert
type
==
Object
.
class
;
return
getGetter
(
type
);
}
@Override
...
...
@@ -259,7 +248,16 @@ public final class UserAccessorProperty extends SpillProperty {
@Override
public
MethodHandle
getSetter
(
final
Class
<?>
type
,
final
PropertyMap
currentMap
)
{
return
INVOKE_SETTER_ACCESSOR
;
if
(
type
==
int
.
class
)
{
return
INVOKE_INT_SETTER
;
}
else
if
(
type
==
long
.
class
)
{
return
INVOKE_LONG_SETTER
;
}
else
if
(
type
==
double
.
class
)
{
return
INVOKE_NUMBER_SETTER
;
}
else
{
assert
type
==
Object
.
class
;
return
INVOKE_OBJECT_SETTER
;
}
}
@Override
...
...
@@ -282,31 +280,81 @@ public final class UserAccessorProperty extends SpillProperty {
// getter/setter may be inherited. If so, proto is bound during lookup. In either
// inherited or self case, slot is also bound during lookup. Actual ScriptFunction
// to be called is retrieved everytime and applied.
private
static
Object
invokeGetterAccessor
(
final
Accessors
gs
,
final
Object
self
)
{
@SuppressWarnings
(
"unused"
)
private
static
Object
invokeObjectGetter
(
final
Accessors
gs
,
final
MethodHandle
invoker
,
final
Object
self
)
throws
Throwable
{
final
Object
func
=
gs
.
getter
;
if
(
func
instanceof
ScriptFunction
)
{
try
{
return
getINVOKE_UA_GETTER
().
invokeExact
(
func
,
self
);
}
catch
(
final
Error
|
RuntimeException
t
)
{
throw
t
;
}
catch
(
final
Throwable
t
)
{
throw
new
RuntimeException
(
t
);
}
return
invoker
.
invokeExact
(
func
,
self
);
}
return
UNDEFINED
;
}
private
static
void
invokeSetterAccessor
(
final
Accessors
gs
,
final
String
name
,
final
Object
self
,
final
Object
value
)
{
@SuppressWarnings
(
"unused"
)
private
static
int
invokeIntGetter
(
final
Accessors
gs
,
final
MethodHandle
invoker
,
final
int
programPoint
,
final
Object
self
)
throws
Throwable
{
final
Object
func
=
gs
.
getter
;
if
(
func
instanceof
ScriptFunction
)
{
return
(
int
)
invoker
.
invokeExact
(
func
,
self
);
}
throw
new
UnwarrantedOptimismException
(
UNDEFINED
,
programPoint
);
}
@SuppressWarnings
(
"unused"
)
private
static
long
invokeLongGetter
(
final
Accessors
gs
,
final
MethodHandle
invoker
,
final
int
programPoint
,
final
Object
self
)
throws
Throwable
{
final
Object
func
=
gs
.
getter
;
if
(
func
instanceof
ScriptFunction
)
{
return
(
long
)
invoker
.
invokeExact
(
func
,
self
);
}
throw
new
UnwarrantedOptimismException
(
UNDEFINED
,
programPoint
);
}
@SuppressWarnings
(
"unused"
)
private
static
double
invokeNumberGetter
(
final
Accessors
gs
,
final
MethodHandle
invoker
,
final
int
programPoint
,
final
Object
self
)
throws
Throwable
{
final
Object
func
=
gs
.
getter
;
if
(
func
instanceof
ScriptFunction
)
{
return
(
double
)
invoker
.
invokeExact
(
func
,
self
);
}
throw
new
UnwarrantedOptimismException
(
UNDEFINED
,
programPoint
);
}
@SuppressWarnings
(
"unused"
)
private
static
void
invokeObjectSetter
(
final
Accessors
gs
,
final
MethodHandle
invoker
,
final
String
name
,
final
Object
self
,
final
Object
value
)
throws
Throwable
{
final
Object
func
=
gs
.
setter
;
if
(
func
instanceof
ScriptFunction
)
{
invoker
.
invokeExact
(
func
,
self
,
value
);
}
else
if
(
name
!=
null
)
{
throw
typeError
(
"property.has.no.setter"
,
name
,
ScriptRuntime
.
safeToString
(
self
));
}
}
@SuppressWarnings
(
"unused"
)
private
static
void
invokeIntSetter
(
final
Accessors
gs
,
final
MethodHandle
invoker
,
final
String
name
,
final
Object
self
,
final
int
value
)
throws
Throwable
{
final
Object
func
=
gs
.
setter
;
if
(
func
instanceof
ScriptFunction
)
{
invoker
.
invokeExact
(
func
,
self
,
value
);
}
else
if
(
name
!=
null
)
{
throw
typeError
(
"property.has.no.setter"
,
name
,
ScriptRuntime
.
safeToString
(
self
));
}
}
@SuppressWarnings
(
"unused"
)
private
static
void
invokeLongSetter
(
final
Accessors
gs
,
final
MethodHandle
invoker
,
final
String
name
,
final
Object
self
,
final
long
value
)
throws
Throwable
{
final
Object
func
=
gs
.
setter
;
if
(
func
instanceof
ScriptFunction
)
{
invoker
.
invokeExact
(
func
,
self
,
value
);
}
else
if
(
name
!=
null
)
{
throw
typeError
(
"property.has.no.setter"
,
name
,
ScriptRuntime
.
safeToString
(
self
));
}
}
@SuppressWarnings
(
"unused"
)
private
static
void
invokeNumberSetter
(
final
Accessors
gs
,
final
MethodHandle
invoker
,
final
String
name
,
final
Object
self
,
final
double
value
)
throws
Throwable
{
final
Object
func
=
gs
.
setter
;
if
(
func
instanceof
ScriptFunction
)
{
try
{
getINVOKE_UA_SETTER
().
invokeExact
(
func
,
self
,
value
);
}
catch
(
final
Error
|
RuntimeException
t
)
{
throw
t
;
}
catch
(
final
Throwable
t
)
{
throw
new
RuntimeException
(
t
);
}
invoker
.
invokeExact
(
func
,
self
,
value
);
}
else
if
(
name
!=
null
)
{
throw
typeError
(
"property.has.no.setter"
,
name
,
ScriptRuntime
.
safeToString
(
self
));
}
...
...
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java
浏览文件 @
333ac25a
...
...
@@ -335,6 +335,20 @@ public final class Bootstrap {
return
createDynamicInvoker
(
opDesc
,
MethodType
.
methodType
(
rtype
,
ptypes
));
}
/**
* Returns a dynamic invoker for a specified dynamic operation using the public lookup. Similar to
* {@link #createDynamicInvoker(String, Class, Class...)} but with an additional parameter to
* set the call site flags of the dynamic invoker.
* @param opDesc Dynalink dynamic operation descriptor.
* @param flags the call site flags for the operation
* @param rtype the return type for the operation
* @param ptypes the parameter types for the operation
* @return MethodHandle for invoking the operation.
*/
public
static
MethodHandle
createDynamicInvoker
(
final
String
opDesc
,
final
int
flags
,
final
Class
<?>
rtype
,
final
Class
<?>...
ptypes
)
{
return
bootstrap
(
MethodHandles
.
publicLookup
(),
opDesc
,
MethodType
.
methodType
(
rtype
,
ptypes
),
flags
).
dynamicInvoker
();
}
/**
* Returns a dynamic invoker for a specified dynamic operation using the public lookup. Similar to
* {@link #createDynamicInvoker(String, Class, Class...)} but with return and parameter types composed into a
...
...
nashorn/test/examples/getter-setter-micro.js
0 → 100644
浏览文件 @
333ac25a
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* A micro-benchmark for getters and setters with primitive values,
* alternating between ints and doubles. Introduction of primitive
* and optimistic user accessors in JDK-8062401 make this faster by
* 10x or more by allowing inlining and other optimizations to take place.
*/
var
x
=
{
get
m
()
{
return
this
.
_m
;
},
set
m
(
v
)
{
this
.
_m
=
v
;
},
get
n
()
{
return
this
.
_n
;
},
set
n
(
v
)
{
this
.
_n
=
v
;
}
};
function
bench
(
v1
,
v2
,
result
)
{
var
start
=
Date
.
now
();
x
.
n
=
v1
;
for
(
var
i
=
0
;
i
<
1
e8
;
i
++
)
{
x
.
m
=
v2
;
if
(
x
.
m
+
x
.
n
!==
result
)
{
throw
"
wrong result
"
;
}
}
print
(
"
done in
"
,
Date
.
now
()
-
start
,
"
millis
"
);
}
for
(
var
i
=
0
;
i
<
10
;
i
++
)
{
bench
(
i
,
4
,
4
+
i
);
}
for
(
var
i
=
0
;
i
<
10
;
i
++
)
{
bench
(
i
,
4.5
,
4.5
+
i
);
}
for
(
var
i
=
0
;
i
<
10
;
i
++
)
{
bench
(
i
,
5
,
5
+
i
);
}
for
(
var
i
=
0
;
i
<
10
;
i
++
)
{
bench
(
i
,
5.5
,
5.5
+
i
);
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录