Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_nashorn
提交
d8080e04
D
dragonwell8_nashorn
项目概览
openanolis
/
dragonwell8_nashorn
通知
2
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_nashorn
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
d8080e04
编写于
5月 24, 2013
作者:
H
hannesw
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8011630: JSON parsing performance issue
Reviewed-by: lagergren, sundar
上级
d5c328f7
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
231 addition
and
140 deletion
+231
-140
src/jdk/nashorn/internal/objects/NativeArguments.java
src/jdk/nashorn/internal/objects/NativeArguments.java
+5
-0
src/jdk/nashorn/internal/runtime/AccessorProperty.java
src/jdk/nashorn/internal/runtime/AccessorProperty.java
+98
-18
src/jdk/nashorn/internal/runtime/FindProperty.java
src/jdk/nashorn/internal/runtime/FindProperty.java
+19
-0
src/jdk/nashorn/internal/runtime/Property.java
src/jdk/nashorn/internal/runtime/Property.java
+20
-0
src/jdk/nashorn/internal/runtime/ScriptObject.java
src/jdk/nashorn/internal/runtime/ScriptObject.java
+12
-112
src/jdk/nashorn/internal/runtime/SetMethodCreator.java
src/jdk/nashorn/internal/runtime/SetMethodCreator.java
+1
-8
src/jdk/nashorn/internal/runtime/UserAccessorProperty.java
src/jdk/nashorn/internal/runtime/UserAccessorProperty.java
+76
-2
未找到文件。
src/jdk/nashorn/internal/objects/NativeArguments.java
浏览文件 @
d8080e04
...
...
@@ -603,6 +603,11 @@ public final class NativeArguments extends ScriptObject {
}
}
@Override
public
Object
getLength
()
{
return
length
;
}
private
Object
getArgumentsLength
()
{
return
length
;
}
...
...
src/jdk/nashorn/internal/runtime/AccessorProperty.java
浏览文件 @
d8080e04
...
...
@@ -75,7 +75,23 @@ public class AccessorProperty extends Property {
private
static
final
MethodType
[]
ACCESSOR_GETTER_TYPES
=
new
MethodType
[
NOOF_TYPES
];
private
static
final
MethodType
[]
ACCESSOR_SETTER_TYPES
=
new
MethodType
[
NOOF_TYPES
];
private
static
final
MethodHandle
SPILLGETTER
=
MH
.
asType
(
MH
.
getter
(
MethodHandles
.
lookup
(),
ScriptObject
.
class
,
"spill"
,
Object
[].
class
),
Lookup
.
GET_OBJECT_TYPE
);
private
static
final
MethodHandle
SPILL_ELEMENT_GETTER
;
private
static
final
MethodHandle
SPILL_ELEMENT_SETTER
;
private
static
final
int
SPILL_CACHE_SIZE
=
8
;
private
static
final
MethodHandle
[]
SPILL_ACCESSORS
=
new
MethodHandle
[
SPILL_CACHE_SIZE
*
2
];
static
{
for
(
int
i
=
0
;
i
<
NOOF_TYPES
;
i
++)
{
final
Type
type
=
ACCESSOR_TYPES
.
get
(
i
);
ACCESSOR_GETTER_TYPES
[
i
]
=
MH
.
type
(
type
.
getTypeClass
(),
Object
.
class
);
ACCESSOR_SETTER_TYPES
[
i
]
=
MH
.
type
(
void
.
class
,
Object
.
class
,
type
.
getTypeClass
());
}
final
MethodHandle
spillGetter
=
MH
.
getter
(
MethodHandles
.
lookup
(),
ScriptObject
.
class
,
"spill"
,
Object
[].
class
);
SPILL_ELEMENT_GETTER
=
MH
.
filterArguments
(
MH
.
arrayElementGetter
(
Object
[].
class
),
0
,
spillGetter
);
SPILL_ELEMENT_SETTER
=
MH
.
filterArguments
(
MH
.
arrayElementSetter
(
Object
[].
class
),
0
,
spillGetter
);
}
/** Seed getter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */
private
MethodHandle
primitiveGetter
;
...
...
@@ -96,14 +112,6 @@ public class AccessorProperty extends Property {
*/
private
Class
<?>
currentType
;
static
{
for
(
int
i
=
0
;
i
<
NOOF_TYPES
;
i
++)
{
final
Type
type
=
ACCESSOR_TYPES
.
get
(
i
);
ACCESSOR_GETTER_TYPES
[
i
]
=
MH
.
type
(
type
.
getTypeClass
(),
Object
.
class
);
ACCESSOR_SETTER_TYPES
[
i
]
=
MH
.
type
(
void
.
class
,
Object
.
class
,
type
.
getTypeClass
());
}
}
/**
* Delegate constructor. This is used when adding properties to the Global scope, which
* is necessary for outermost levels in a script (the ScriptObject is represented by
...
...
@@ -114,18 +122,30 @@ public class AccessorProperty extends Property {
* @param delegate delegate script object to rebind receiver to
*/
public
AccessorProperty
(
final
AccessorProperty
property
,
final
ScriptObject
delegate
)
{
this
(
property
);
this
.
getters
=
new
MethodHandle
[
NOOF_TYPES
];
super
(
property
);
this
.
primitiveGetter
=
bindTo
(
primitiveGetter
,
delegate
);
this
.
primitiveSetter
=
bindTo
(
primitiveSetter
,
delegate
);
this
.
objectGetter
=
bindTo
(
objectGetter
,
delegate
);
this
.
objectSetter
=
bindTo
(
objectSetter
,
delegate
);
this
.
primitiveGetter
=
bindTo
(
pr
operty
.
pr
imitiveGetter
,
delegate
);
this
.
primitiveSetter
=
bindTo
(
pr
operty
.
pr
imitiveSetter
,
delegate
);
this
.
objectGetter
=
bindTo
(
property
.
objectGetter
,
delegate
);
this
.
objectSetter
=
bindTo
(
property
.
objectSetter
,
delegate
);
setCurrentType
(
property
.
getCurrentType
());
}
/**
* Constructor for spill properties. Array getters and setters will be created on demand.
*
* @param key the property key
* @param flags the property flags
* @param slot spill slot
*/
public
AccessorProperty
(
final
String
key
,
final
int
flags
,
final
int
slot
)
{
super
(
key
,
flags
,
slot
);
assert
(
flags
&
IS_SPILL
)
==
IS_SPILL
;
setCurrentType
(
Object
.
class
);
}
/**
* Constructor. Similar to the constructor with both primitive getters and setters, the difference
* here being that only one getter and setter (setter is optional for non writable fields) is given
...
...
@@ -267,8 +287,41 @@ public class AccessorProperty extends Property {
return
new
AccessorProperty
(
this
);
}
@Override
protected
void
setObjectValue
(
final
ScriptObject
self
,
final
ScriptObject
owner
,
final
Object
value
,
final
boolean
strict
)
{
if
(
isSpill
())
{
self
.
spill
[
getSlot
()]
=
value
;
}
else
{
try
{
getSetter
(
Object
.
class
,
self
.
getMap
()).
invokeExact
((
Object
)
self
,
value
);
}
catch
(
final
Error
|
RuntimeException
e
)
{
throw
e
;
}
catch
(
final
Throwable
e
)
{
throw
new
RuntimeException
(
e
);
}
}
}
@Override
protected
Object
getObjectValue
(
final
ScriptObject
self
,
final
ScriptObject
owner
)
{
if
(
isSpill
())
{
return
self
.
spill
[
getSlot
()];
}
else
{
try
{
return
getGetter
(
Object
.
class
).
invokeExact
((
Object
)
self
);
}
catch
(
final
Error
|
RuntimeException
e
)
{
throw
e
;
}
catch
(
final
Throwable
e
)
{
throw
new
RuntimeException
(
e
);
}
}
}
@Override
public
MethodHandle
getGetter
(
final
Class
<?>
type
)
{
if
(
isSpill
()
&&
objectGetter
==
null
)
{
objectGetter
=
getSpillGetter
();
}
final
int
i
=
getAccessorTypeIndex
(
type
);
if
(
getters
[
i
]
==
null
)
{
getters
[
i
]
=
debug
(
...
...
@@ -284,7 +337,7 @@ public class AccessorProperty extends Property {
"get"
);
}
return
isSpill
()
?
MH
.
filterArguments
(
getters
[
i
],
0
,
SPILLGETTER
)
:
getters
[
i
];
return
getters
[
i
];
}
private
Property
getWiderProperty
(
final
Class
<?>
type
)
{
...
...
@@ -313,6 +366,9 @@ public class AccessorProperty extends Property {
}
private
MethodHandle
generateSetter
(
final
Class
<?>
forType
,
final
Class
<?>
type
)
{
if
(
isSpill
()
&&
objectSetter
==
null
)
{
objectSetter
=
getSpillSetter
();
}
MethodHandle
mh
=
createSetter
(
forType
,
type
,
primitiveSetter
,
objectSetter
);
mh
=
MH
.
asType
(
mh
,
ACCESSOR_SETTER_TYPES
[
getAccessorTypeIndex
(
type
)]);
//has to be the case for invokeexact to work in ScriptObject
mh
=
debug
(
mh
,
currentType
,
type
,
"set"
);
...
...
@@ -343,7 +399,7 @@ public class AccessorProperty extends Property {
mh
=
generateSetter
(
forType
,
type
);
}
return
isSpill
()
?
MH
.
filterArguments
(
mh
,
0
,
SPILLGETTER
)
:
mh
;
return
mh
;
}
@Override
...
...
@@ -363,6 +419,30 @@ public class AccessorProperty extends Property {
setCurrentType
(
newType
);
}
private
MethodHandle
getSpillGetter
()
{
final
int
slot
=
getSlot
();
MethodHandle
getter
=
slot
<
SPILL_CACHE_SIZE
?
SPILL_ACCESSORS
[
slot
*
2
]
:
null
;
if
(
getter
==
null
)
{
getter
=
MH
.
asType
(
MH
.
insertArguments
(
SPILL_ELEMENT_GETTER
,
1
,
slot
),
Lookup
.
GET_OBJECT_TYPE
);
if
(
slot
<
SPILL_CACHE_SIZE
)
{
SPILL_ACCESSORS
[
slot
*
2
]
=
getter
;
}
}
return
getter
;
}
private
MethodHandle
getSpillSetter
()
{
final
int
slot
=
getSlot
();
MethodHandle
setter
=
slot
<
SPILL_CACHE_SIZE
?
SPILL_ACCESSORS
[
slot
*
2
+
1
]
:
null
;
if
(
setter
==
null
)
{
setter
=
MH
.
asType
(
MH
.
insertArguments
(
SPILL_ELEMENT_SETTER
,
1
,
slot
),
Lookup
.
SET_OBJECT_TYPE
);
if
(
slot
<
SPILL_CACHE_SIZE
)
{
SPILL_ACCESSORS
[
slot
*
2
+
1
]
=
setter
;
}
}
return
setter
;
}
private
static
void
finest
(
final
String
str
)
{
if
(
DEBUG_FIELDS
)
{
LOG
.
finest
(
str
);
...
...
src/jdk/nashorn/internal/runtime/FindProperty.java
浏览文件 @
d8080e04
...
...
@@ -153,5 +153,24 @@ public final class FindProperty {
return
prototype
.
isScope
();
}
/**
* Get the property value from self as object.
*
* @return the property value
*/
public
Object
getObjectValue
()
{
return
property
.
getObjectValue
(
getGetterReceiver
(),
getOwner
());
}
/**
* Set the property value in self.
*
* @param value the new value
* @param strict strict flag
*/
public
void
setObjectValue
(
final
Object
value
,
final
boolean
strict
)
{
property
.
setObjectValue
(
getSetterReceiver
(),
getOwner
(),
value
,
strict
);
}
}
src/jdk/nashorn/internal/runtime/Property.java
浏览文件 @
d8080e04
...
...
@@ -351,6 +351,26 @@ public abstract class Property {
return
slot
;
}
/**
* Set the value of this property in {@code owner}. This allows to bypass creation of the
* setter MethodHandle for spill and user accessor properties.
*
* @param self the this object
* @param owner the owner object
* @param value the new property value
*/
protected
abstract
void
setObjectValue
(
ScriptObject
self
,
ScriptObject
owner
,
Object
value
,
boolean
strict
);
/**
* Set the Object value of this property from {@code owner}. This allows to bypass creation of the
* getter MethodHandle for spill and user accessor properties.
*
* @param self the this object
* @param owner the owner object
* @return the property value
*/
protected
abstract
Object
getObjectValue
(
ScriptObject
self
,
ScriptObject
owner
);
/**
* Abstract method for retrieving the setter for the property. We do not know
* anything about the internal representation when we request the setter, we only
...
...
src/jdk/nashorn/internal/runtime/ScriptObject.java
浏览文件 @
d8080e04
...
...
@@ -25,7 +25,6 @@
package
jdk.nashorn.internal.runtime
;
import
static
jdk
.
nashorn
.
internal
.
codegen
.
CompilerConstants
.
staticCall
;
import
static
jdk
.
nashorn
.
internal
.
codegen
.
CompilerConstants
.
virtualCall
;
import
static
jdk
.
nashorn
.
internal
.
codegen
.
CompilerConstants
.
virtualCallNoLookup
;
import
static
jdk
.
nashorn
.
internal
.
lookup
.
Lookup
.
MH
;
...
...
@@ -151,17 +150,6 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
/** Method handle for setting the user accessors of a ScriptObject */
public
static
final
Call
SET_USER_ACCESSORS
=
virtualCall
(
ScriptObject
.
class
,
"setUserAccessors"
,
void
.
class
,
String
.
class
,
ScriptFunction
.
class
,
ScriptFunction
.
class
);
/** Method handle for getter for {@link UserAccessorProperty}, given a slot */
static
final
Call
USER_ACCESSOR_GETTER
=
staticCall
(
MethodHandles
.
lookup
(),
ScriptObject
.
class
,
"userAccessorGetter"
,
Object
.
class
,
ScriptObject
.
class
,
int
.
class
,
Object
.
class
);
/** Method handle for setter for {@link UserAccessorProperty}, given a slot */
static
final
Call
USER_ACCESSOR_SETTER
=
staticCall
(
MethodHandles
.
lookup
(),
ScriptObject
.
class
,
"userAccessorSetter"
,
void
.
class
,
ScriptObject
.
class
,
int
.
class
,
String
.
class
,
Object
.
class
,
Object
.
class
);
private
static
final
MethodHandle
INVOKE_UA_GETTER
=
Bootstrap
.
createDynamicInvoker
(
"dyn:call"
,
Object
.
class
,
Object
.
class
,
Object
.
class
);
private
static
final
MethodHandle
INVOKE_UA_SETTER
=
Bootstrap
.
createDynamicInvoker
(
"dyn:call"
,
void
.
class
,
Object
.
class
,
Object
.
class
,
Object
.
class
);
/**
* Constructor
*/
...
...
@@ -699,17 +687,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
* @return New property.
*/
public
final
Property
addOwnProperty
(
final
String
key
,
final
int
propertyFlags
,
final
Object
value
)
{
final
MethodHandle
setter
=
addSpill
(
key
,
propertyFlags
);
try
{
setter
.
invokeExact
((
Object
)
this
,
value
);
}
catch
(
final
Error
|
RuntimeException
e
)
{
throw
e
;
}
catch
(
final
Throwable
e
)
{
throw
new
RuntimeException
(
e
);
}
return
getMap
().
findProperty
(
key
);
final
Property
property
=
addSpillProperty
(
key
,
propertyFlags
);
property
.
setObjectValue
(
this
,
this
,
value
,
false
);
return
property
;
}
/**
...
...
@@ -744,15 +724,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
// Erase the property field value with undefined. If the property is defined
// by user-defined accessors, we don't want to call the setter!!
if
(!(
property
instanceof
UserAccessorProperty
))
{
try
{
// make the property value to be undefined
//TODO specproperties
property
.
getSetter
(
Object
.
class
,
getMap
()).
invokeExact
((
Object
)
this
,
(
Object
)
UNDEFINED
);
}
catch
(
final
RuntimeException
|
Error
e
)
{
throw
e
;
}
catch
(
final
Throwable
t
)
{
throw
new
RuntimeException
(
t
);
}
property
.
setObjectValue
(
this
,
this
,
UNDEFINED
,
false
);
}
}
...
...
@@ -948,18 +920,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
* @return the value of the property
*/
protected
static
Object
getObjectValue
(
final
FindProperty
find
)
{
final
MethodHandle
getter
=
find
.
getGetter
(
Object
.
class
);
if
(
getter
!=
null
)
{
try
{
return
getter
.
invokeExact
((
Object
)
find
.
getGetterReceiver
());
}
catch
(
final
Error
|
RuntimeException
e
)
{
throw
e
;
}
catch
(
final
Throwable
e
)
{
throw
new
RuntimeException
(
e
);
}
}
return
UNDEFINED
;
return
find
.
getObjectValue
();
}
/**
...
...
@@ -2087,11 +2048,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
property
=
addOwnProperty
(
property
);
}
else
{
int
i
=
getMap
().
getSpillLength
();
MethodHandle
getter
=
MH
.
arrayElementGetter
(
Object
[].
class
);
MethodHandle
setter
=
MH
.
arrayElementSetter
(
Object
[].
class
);
getter
=
MH
.
asType
(
MH
.
insertArguments
(
getter
,
1
,
i
),
Lookup
.
GET_OBJECT_TYPE
);
setter
=
MH
.
asType
(
MH
.
insertArguments
(
setter
,
1
,
i
),
Lookup
.
SET_OBJECT_TYPE
);
property
=
new
AccessorProperty
(
key
,
propertyFlags
|
Property
.
IS_SPILL
,
i
,
getter
,
setter
);
property
=
new
AccessorProperty
(
key
,
propertyFlags
|
Property
.
IS_SPILL
,
i
);
notifyPropertyAdded
(
this
,
property
);
property
=
addOwnProperty
(
property
);
i
=
property
.
getSlot
();
...
...
@@ -2115,20 +2072,15 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
/**
* Add a spill entry for the given key.
* @param key Property key.
* @param propertyFlags Property flags.
* @param key Property key.
* @return Setter method handle.
*/
private
MethodHandle
addSpill
(
final
String
key
,
final
int
propertyFlags
)
{
final
Property
spillProperty
=
addSpillProperty
(
key
,
propertyFlags
);
MethodHandle
addSpill
(
final
String
key
)
{
final
Property
spillProperty
=
addSpillProperty
(
key
,
0
);
final
Class
<?>
type
=
Object
.
class
;
return
spillProperty
.
getSetter
(
type
,
getMap
());
//TODO specfields
}
MethodHandle
addSpill
(
final
String
key
)
{
return
addSpill
(
key
,
0
);
}
/**
* Make sure arguments are paired correctly, with respect to more parameters than declared,
* fewer parameters than declared and other things that JavaScript allows. This might involve
...
...
@@ -2659,14 +2611,8 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
return
;
}
try
{
final
MethodHandle
setter
=
f
.
getSetter
(
Object
.
class
,
strict
);
//TODO specfields
setter
.
invokeExact
((
Object
)
f
.
getSetterReceiver
(),
value
);
}
catch
(
final
Error
|
RuntimeException
e
)
{
throw
e
;
}
catch
(
final
Throwable
e
)
{
throw
new
RuntimeException
(
e
);
}
f
.
setObjectValue
(
value
,
strict
);
}
else
if
(!
isExtensible
())
{
if
(
strict
)
{
throw
typeError
(
"object.non.extensible"
,
key
,
ScriptRuntime
.
safeToString
(
this
));
...
...
@@ -2677,13 +2623,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
}
private
void
spill
(
final
String
key
,
final
Object
value
)
{
try
{
addSpill
(
key
).
invokeExact
((
Object
)
this
,
value
);
}
catch
(
final
Error
|
RuntimeException
e
)
{
throw
e
;
}
catch
(
final
Throwable
e
)
{
throw
new
RuntimeException
(
e
);
}
addSpillProperty
(
key
,
0
).
setObjectValue
(
this
,
this
,
value
,
false
);
}
...
...
@@ -3217,46 +3157,6 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
return
(
index
<
0
||
(
index
>=
spill
.
length
))
?
null
:
spill
[
index
];
}
// User defined getter and setter are always called by "dyn:call". Note that the user
// 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.
@SuppressWarnings
(
"unused"
)
private
static
Object
userAccessorGetter
(
final
ScriptObject
proto
,
final
int
slot
,
final
Object
self
)
{
final
ScriptObject
container
=
(
proto
!=
null
)
?
proto
:
(
ScriptObject
)
self
;
final
Object
func
=
container
.
getSpill
(
slot
);
if
(
func
instanceof
ScriptFunction
)
{
try
{
return
INVOKE_UA_GETTER
.
invokeExact
(
func
,
self
);
}
catch
(
final
Error
|
RuntimeException
t
)
{
throw
t
;
}
catch
(
final
Throwable
t
)
{
throw
new
RuntimeException
(
t
);
}
}
return
UNDEFINED
;
}
@SuppressWarnings
(
"unused"
)
private
static
void
userAccessorSetter
(
final
ScriptObject
proto
,
final
int
slot
,
final
String
name
,
final
Object
self
,
final
Object
value
)
{
final
ScriptObject
container
=
(
proto
!=
null
)
?
proto
:
(
ScriptObject
)
self
;
final
Object
func
=
container
.
getSpill
(
slot
);
if
(
func
instanceof
ScriptFunction
)
{
try
{
INVOKE_UA_SETTER
.
invokeExact
(
func
,
self
,
value
);
}
catch
(
final
Error
|
RuntimeException
t
)
{
throw
t
;
}
catch
(
final
Throwable
t
)
{
throw
new
RuntimeException
(
t
);
}
}
else
if
(
name
!=
null
)
{
throw
typeError
(
"property.has.no.setter"
,
name
,
ScriptRuntime
.
safeToString
(
self
));
}
}
private
static
MethodHandle
findOwnMH
(
final
String
name
,
final
Class
<?>
rtype
,
final
Class
<?>...
types
)
{
final
Class
<?>
own
=
ScriptObject
.
class
;
final
MethodType
mt
=
MH
.
type
(
rtype
,
types
);
...
...
src/jdk/nashorn/internal/runtime/SetMethodCreator.java
浏览文件 @
d8080e04
...
...
@@ -183,17 +183,10 @@ final class SetMethodCreator {
private
SetMethod
createNewSpillPropertySetter
()
{
final
int
nextSpill
=
getMap
().
getSpillLength
();
final
Property
property
=
createSpillProperty
(
nextSpill
);
final
Property
property
=
new
AccessorProperty
(
getName
(),
Property
.
IS_SPILL
,
nextSpill
);
return
new
SetMethod
(
createSpillMethodHandle
(
nextSpill
,
property
),
property
);
}
private
Property
createSpillProperty
(
final
int
nextSpill
)
{
final
MethodHandle
getter
=
MH
.
asType
(
MH
.
insertArguments
(
MH
.
arrayElementGetter
(
Object
[].
class
),
1
,
nextSpill
),
Lookup
.
GET_OBJECT_TYPE
);
final
MethodHandle
setter
=
MH
.
asType
(
MH
.
insertArguments
(
MH
.
arrayElementSetter
(
Object
[].
class
),
1
,
nextSpill
),
Lookup
.
SET_OBJECT_TYPE
);
return
new
AccessorProperty
(
getName
(),
Property
.
IS_SPILL
,
nextSpill
,
getter
,
setter
);
}
private
MethodHandle
createSpillMethodHandle
(
final
int
nextSpill
,
Property
property
)
{
final
PropertyMap
oldMap
=
getMap
();
final
PropertyMap
newMap
=
getNewMap
(
property
);
...
...
src/jdk/nashorn/internal/runtime/UserAccessorProperty.java
浏览文件 @
d8080e04
...
...
@@ -26,7 +26,15 @@
package
jdk.nashorn.internal.runtime
;
import
java.lang.invoke.MethodHandle
;
import
java.lang.invoke.MethodHandles
;
import
jdk.nashorn.internal.codegen.CompilerConstants
;
import
jdk.nashorn.internal.lookup.Lookup
;
import
jdk.nashorn.internal.runtime.linker.Bootstrap
;
import
static
jdk
.
nashorn
.
internal
.
codegen
.
CompilerConstants
.
staticCall
;
import
static
jdk
.
nashorn
.
internal
.
runtime
.
ECMAErrors
.
typeError
;
import
static
jdk
.
nashorn
.
internal
.
runtime
.
ScriptRuntime
.
UNDEFINED
;
/**
* Property with user defined getters/setters. Actual getter and setter
...
...
@@ -51,6 +59,22 @@ public final class UserAccessorProperty extends Property {
/** User defined setter function slot. */
private
final
int
setterSlot
;
/** Getter method handle */
private
final
static
CompilerConstants
.
Call
USER_ACCESSOR_GETTER
=
staticCall
(
MethodHandles
.
lookup
(),
UserAccessorProperty
.
class
,
"userAccessorGetter"
,
Object
.
class
,
ScriptObject
.
class
,
int
.
class
,
Object
.
class
);
/** Setter method handle */
private
final
static
CompilerConstants
.
Call
USER_ACCESSOR_SETTER
=
staticCall
(
MethodHandles
.
lookup
(),
UserAccessorProperty
.
class
,
"userAccessorSetter"
,
void
.
class
,
ScriptObject
.
class
,
int
.
class
,
String
.
class
,
Object
.
class
,
Object
.
class
);
/** Dynamic invoker for getter */
private
static
final
MethodHandle
INVOKE_UA_GETTER
=
Bootstrap
.
createDynamicInvoker
(
"dyn:call"
,
Object
.
class
,
Object
.
class
,
Object
.
class
);
/** Dynamic invoker for setter */
private
static
final
MethodHandle
INVOKE_UA_SETTER
=
Bootstrap
.
createDynamicInvoker
(
"dyn:call"
,
void
.
class
,
Object
.
class
,
Object
.
class
,
Object
.
class
);
/**
* Constructor
*
...
...
@@ -133,9 +157,19 @@ public final class UserAccessorProperty extends Property {
return
setterSlot
>
-
1
;
}
@Override
protected
Object
getObjectValue
(
final
ScriptObject
self
,
final
ScriptObject
owner
)
{
return
userAccessorGetter
(
owner
,
getGetterSlot
(),
self
);
}
@Override
protected
void
setObjectValue
(
final
ScriptObject
self
,
final
ScriptObject
owner
,
final
Object
value
,
final
boolean
strict
)
{
userAccessorSetter
(
owner
,
getSetterSlot
(),
strict
?
getKey
()
:
null
,
self
,
value
);
}
@Override
public
MethodHandle
getGetter
(
final
Class
<?>
type
)
{
return
Lookup
.
filterReturnType
(
ScriptObject
.
USER_ACCESSOR_GETTER
.
methodHandle
(),
type
);
return
Lookup
.
filterReturnType
(
USER_ACCESSOR_GETTER
.
methodHandle
(),
type
);
}
@Override
...
...
@@ -146,7 +180,7 @@ public final class UserAccessorProperty extends Property {
@Override
public
MethodHandle
getSetter
(
final
Class
<?>
type
,
final
PropertyMap
currentMap
)
{
return
ScriptObject
.
USER_ACCESSOR_SETTER
.
methodHandle
();
return
USER_ACCESSOR_SETTER
.
methodHandle
();
}
@Override
...
...
@@ -155,4 +189,44 @@ public final class UserAccessorProperty extends Property {
return
(
value
instanceof
ScriptFunction
)
?
(
ScriptFunction
)
value
:
null
;
}
// User defined getter and setter are always called by "dyn:call". Note that the user
// 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.
@SuppressWarnings
(
"unused"
)
static
Object
userAccessorGetter
(
final
ScriptObject
proto
,
final
int
slot
,
final
Object
self
)
{
final
ScriptObject
container
=
(
proto
!=
null
)
?
proto
:
(
ScriptObject
)
self
;
final
Object
func
=
container
.
getSpill
(
slot
);
if
(
func
instanceof
ScriptFunction
)
{
try
{
return
INVOKE_UA_GETTER
.
invokeExact
(
func
,
self
);
}
catch
(
final
Error
|
RuntimeException
t
)
{
throw
t
;
}
catch
(
final
Throwable
t
)
{
throw
new
RuntimeException
(
t
);
}
}
return
UNDEFINED
;
}
@SuppressWarnings
(
"unused"
)
static
void
userAccessorSetter
(
final
ScriptObject
proto
,
final
int
slot
,
final
String
name
,
final
Object
self
,
final
Object
value
)
{
final
ScriptObject
container
=
(
proto
!=
null
)
?
proto
:
(
ScriptObject
)
self
;
final
Object
func
=
container
.
getSpill
(
slot
);
if
(
func
instanceof
ScriptFunction
)
{
try
{
INVOKE_UA_SETTER
.
invokeExact
(
func
,
self
,
value
);
}
catch
(
final
Error
|
RuntimeException
t
)
{
throw
t
;
}
catch
(
final
Throwable
t
)
{
throw
new
RuntimeException
(
t
);
}
}
else
if
(
name
!=
null
)
{
throw
typeError
(
"property.has.no.setter"
,
name
,
ScriptRuntime
.
safeToString
(
self
));
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录