Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell11
提交
b642e31e
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,发现更多精彩内容 >>
提交
b642e31e
编写于
9月 16, 2015
作者:
H
hannesw
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8134609: Allow constructors with same prototoype map to share the allocator map
Reviewed-by: attila, sundar
上级
92853b17
变更
15
展开全部
显示空白变更内容
内联
并排
Showing
15 changed file
with
655 addition
and
187 deletion
+655
-187
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSAdapter.java
...classes/jdk/nashorn/internal/objects/NativeJSAdapter.java
+3
-3
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AllocationStrategy.java
...sses/jdk/nashorn/internal/runtime/AllocationStrategy.java
+84
-3
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Debug.java
...orn/share/classes/jdk/nashorn/internal/runtime/Debug.java
+11
-0
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyListeners.java
...asses/jdk/nashorn/internal/runtime/PropertyListeners.java
+14
-10
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java
...are/classes/jdk/nashorn/internal/runtime/PropertyMap.java
+170
-119
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
...horn/internal/runtime/RecompilableScriptFunctionData.java
+2
-2
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java
.../classes/jdk/nashorn/internal/runtime/ScriptFunction.java
+23
-19
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunctionData.java
...sses/jdk/nashorn/internal/runtime/ScriptFunctionData.java
+2
-1
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java
...re/classes/jdk/nashorn/internal/runtime/ScriptObject.java
+34
-20
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/SetMethodCreator.java
...lasses/jdk/nashorn/internal/runtime/SetMethodCreator.java
+2
-5
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/SharedPropertyMap.java
...asses/jdk/nashorn/internal/runtime/SharedPropertyMap.java
+100
-0
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/WithObject.java
...hare/classes/jdk/nashorn/internal/runtime/WithObject.java
+15
-4
nashorn/test/script/basic/JDK-8134569.js
nashorn/test/script/basic/JDK-8134569.js
+80
-1
nashorn/test/script/basic/JDK-8134569.js.EXPECTED
nashorn/test/script/basic/JDK-8134569.js.EXPECTED
+20
-0
nashorn/test/script/basic/JDK-8134609.js
nashorn/test/script/basic/JDK-8134609.js
+95
-0
未找到文件。
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSAdapter.java
浏览文件 @
b642e31e
...
...
@@ -627,7 +627,7 @@ public final class NativeJSAdapter extends ScriptObject {
return
new
GuardedInvocation
(
MH
.
dropArguments
(
MH
.
constant
(
Object
.
class
,
func
.
createBound
(
this
,
new
Object
[]
{
name
})),
0
,
Object
.
class
),
testJSAdaptor
(
adaptee
,
null
,
null
,
null
),
adaptee
.
getProtoSwitchPoint
(
__call__
,
find
.
getOwner
())
);
adaptee
.
getProtoSwitchPoint
s
(
__call__
,
find
.
getOwner
()),
null
);
}
}
throw
typeError
(
"no.such.function"
,
desc
.
getNameToken
(
2
),
ScriptRuntime
.
safeToString
(
this
));
...
...
@@ -698,7 +698,7 @@ public final class NativeJSAdapter extends ScriptObject {
return
new
GuardedInvocation
(
methodHandle
,
testJSAdaptor
(
adaptee
,
findData
.
getGetter
(
Object
.
class
,
INVALID_PROGRAM_POINT
,
null
),
findData
.
getOwner
(),
func
),
adaptee
.
getProtoSwitchPoint
(
hook
,
findData
.
getOwner
())
);
adaptee
.
getProtoSwitchPoint
s
(
hook
,
findData
.
getOwner
()),
null
);
}
}
}
...
...
@@ -710,7 +710,7 @@ public final class NativeJSAdapter extends ScriptObject {
final
MethodHandle
methodHandle
=
hook
.
equals
(
__put__
)
?
MH
.
asType
(
Lookup
.
EMPTY_SETTER
,
type
)
:
Lookup
.
emptyGetter
(
type
.
returnType
());
return
new
GuardedInvocation
(
methodHandle
,
testJSAdaptor
(
adaptee
,
null
,
null
,
null
),
adaptee
.
getProtoSwitchPoint
(
hook
,
null
)
);
return
new
GuardedInvocation
(
methodHandle
,
testJSAdaptor
(
adaptee
,
null
,
null
,
null
),
adaptee
.
getProtoSwitchPoint
s
(
hook
,
null
),
null
);
}
}
...
...
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AllocationStrategy.java
浏览文件 @
b642e31e
...
...
@@ -29,6 +29,7 @@ import static jdk.nashorn.internal.lookup.Lookup.MH;
import
java.io.Serializable
;
import
java.lang.invoke.MethodHandle
;
import
java.lang.invoke.MethodHandles
;
import
java.lang.ref.WeakReference
;
import
jdk.nashorn.internal.codegen.Compiler
;
import
jdk.nashorn.internal.codegen.CompilerConstants
;
import
jdk.nashorn.internal.codegen.ObjectClassGenerator
;
...
...
@@ -53,6 +54,9 @@ final public class AllocationStrategy implements Serializable {
/** lazily generated allocator */
private
transient
MethodHandle
allocator
;
/** Last used allocator map */
private
transient
AllocatorMap
lastMap
;
/**
* Construct an allocation strategy with the given map and class name.
* @param fieldCount number of fields in the allocated object
...
...
@@ -71,11 +75,49 @@ final public class AllocationStrategy implements Serializable {
return
allocatorClassName
;
}
PropertyMap
getAllocatorMap
()
{
// Create a new map for each function instance
return
PropertyMap
.
newMap
(
null
,
getAllocatorClassName
(),
0
,
fieldCount
,
0
);
/**
* Get the property map for the allocated object.
* @param prototype the prototype object
* @return the property map
*/
synchronized
PropertyMap
getAllocatorMap
(
final
ScriptObject
prototype
)
{
assert
prototype
!=
null
;
final
PropertyMap
protoMap
=
prototype
.
getMap
();
if
(
lastMap
!=
null
)
{
if
(!
lastMap
.
hasSharedProtoMap
())
{
if
(
lastMap
.
hasSamePrototype
(
prototype
))
{
return
lastMap
.
allocatorMap
;
}
if
(
lastMap
.
hasSameProtoMap
(
protoMap
)
&&
lastMap
.
hasUnchangedProtoMap
())
{
// Convert to shared prototype map. Allocated objects will use the same property map
// that can be used as long as none of the prototypes modify the shared proto map.
final
PropertyMap
allocatorMap
=
PropertyMap
.
newMap
(
null
,
getAllocatorClassName
(),
0
,
fieldCount
,
0
);
final
SharedPropertyMap
sharedProtoMap
=
new
SharedPropertyMap
(
protoMap
);
allocatorMap
.
setSharedProtoMap
(
sharedProtoMap
);
prototype
.
setMap
(
sharedProtoMap
);
lastMap
=
new
AllocatorMap
(
prototype
,
protoMap
,
allocatorMap
);
return
allocatorMap
;
}
}
if
(
lastMap
.
hasValidSharedProtoMap
()
&&
lastMap
.
hasSameProtoMap
(
protoMap
))
{
prototype
.
setMap
(
lastMap
.
getSharedProtoMap
());
return
lastMap
.
allocatorMap
;
}
}
final
PropertyMap
allocatorMap
=
PropertyMap
.
newMap
(
null
,
getAllocatorClassName
(),
0
,
fieldCount
,
0
);
lastMap
=
new
AllocatorMap
(
prototype
,
protoMap
,
allocatorMap
);
return
allocatorMap
;
}
/**
* Allocate an object with the given property map
* @param map the property map
* @return the allocated object
*/
ScriptObject
allocate
(
final
PropertyMap
map
)
{
try
{
if
(
allocator
==
null
)
{
...
...
@@ -94,4 +136,43 @@ final public class AllocationStrategy implements Serializable {
public
String
toString
()
{
return
"AllocationStrategy[fieldCount="
+
fieldCount
+
"]"
;
}
static
class
AllocatorMap
{
final
private
WeakReference
<
ScriptObject
>
prototype
;
final
private
WeakReference
<
PropertyMap
>
prototypeMap
;
private
PropertyMap
allocatorMap
;
AllocatorMap
(
final
ScriptObject
prototype
,
final
PropertyMap
protoMap
,
final
PropertyMap
allocMap
)
{
this
.
prototype
=
new
WeakReference
<>(
prototype
);
this
.
prototypeMap
=
new
WeakReference
<>(
protoMap
);
this
.
allocatorMap
=
allocMap
;
}
boolean
hasSamePrototype
(
final
ScriptObject
proto
)
{
return
prototype
.
get
()
==
proto
;
}
boolean
hasSameProtoMap
(
final
PropertyMap
protoMap
)
{
return
prototypeMap
.
get
()
==
protoMap
||
allocatorMap
.
getSharedProtoMap
()
==
protoMap
;
}
boolean
hasUnchangedProtoMap
()
{
final
ScriptObject
proto
=
prototype
.
get
();
return
proto
!=
null
&&
proto
.
getMap
()
==
prototypeMap
.
get
();
}
boolean
hasSharedProtoMap
()
{
return
getSharedProtoMap
()
!=
null
;
}
boolean
hasValidSharedProtoMap
()
{
return
hasSharedProtoMap
()
&&
getSharedProtoMap
().
isValidSharedProtoMap
();
}
PropertyMap
getSharedProtoMap
()
{
return
allocatorMap
.
getSharedProtoMap
();
}
}
}
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Debug.java
浏览文件 @
b642e31e
...
...
@@ -26,6 +26,8 @@
package
jdk.nashorn.internal.runtime
;
import
static
jdk
.
nashorn
.
internal
.
parser
.
TokenType
.
EOF
;
import
jdk.nashorn.api.scripting.NashornException
;
import
jdk.nashorn.internal.parser.Lexer
;
import
jdk.nashorn.internal.parser.Token
;
import
jdk.nashorn.internal.parser.TokenStream
;
...
...
@@ -62,6 +64,15 @@ public final class Debug {
return
firstJSFrame
(
new
Throwable
());
}
/**
* Return a formatted script stack trace string with frames information separated by '\n'.
* This is a shortcut for {@code NashornException.getScriptStackString(new Throwable())}.
* @return formatted stack trace string
*/
public
static
String
scriptStack
()
{
return
NashornException
.
getScriptStackString
(
new
Throwable
());
}
/**
* Return the system identity hashcode for an object as a human readable
* string
...
...
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyListeners.java
浏览文件 @
b642e31e
...
...
@@ -75,16 +75,20 @@ public class PropertyListeners {
}
/**
* Return
listeners added to this
ScriptObject.
* Return
number of listeners added to a
ScriptObject.
* @param obj the object
* @return the listener count
*/
public
static
int
getListenerCount
(
final
ScriptObject
obj
)
{
final
PropertyListeners
propertyListeners
=
obj
.
getMap
().
getListeners
();
if
(
propertyListeners
!=
null
)
{
return
propertyListeners
.
listeners
==
null
?
0
:
propertyListeners
.
listeners
.
size
();
return
obj
.
getMap
().
getListenerCount
();
}
return
0
;
/**
* Return the number of listeners added to this PropertyListeners instance.
* @return the listener count;
*/
public
int
getListenerCount
()
{
return
listeners
==
null
?
0
:
listeners
.
size
();
}
// Property listener management methods
...
...
@@ -156,7 +160,7 @@ public class PropertyListeners {
final
WeakPropertyMapSet
set
=
listeners
.
get
(
prop
.
getKey
());
if
(
set
!=
null
)
{
for
(
final
PropertyMap
propertyMap
:
set
.
elements
())
{
propertyMap
.
propertyAdded
(
prop
);
propertyMap
.
propertyAdded
(
prop
,
false
);
}
listeners
.
remove
(
prop
.
getKey
());
if
(
Context
.
DEBUG
)
{
...
...
@@ -176,7 +180,7 @@ public class PropertyListeners {
final
WeakPropertyMapSet
set
=
listeners
.
get
(
prop
.
getKey
());
if
(
set
!=
null
)
{
for
(
final
PropertyMap
propertyMap
:
set
.
elements
())
{
propertyMap
.
propertyDeleted
(
prop
);
propertyMap
.
propertyDeleted
(
prop
,
false
);
}
listeners
.
remove
(
prop
.
getKey
());
if
(
Context
.
DEBUG
)
{
...
...
@@ -198,7 +202,7 @@ public class PropertyListeners {
final
WeakPropertyMapSet
set
=
listeners
.
get
(
oldProp
.
getKey
());
if
(
set
!=
null
)
{
for
(
final
PropertyMap
propertyMap
:
set
.
elements
())
{
propertyMap
.
propertyModified
(
oldProp
,
newProp
);
propertyMap
.
propertyModified
(
oldProp
,
newProp
,
false
);
}
listeners
.
remove
(
oldProp
.
getKey
());
if
(
Context
.
DEBUG
)
{
...
...
@@ -215,7 +219,7 @@ public class PropertyListeners {
if
(
listeners
!=
null
)
{
for
(
final
WeakPropertyMapSet
set
:
listeners
.
values
())
{
for
(
final
PropertyMap
propertyMap
:
set
.
elements
())
{
propertyMap
.
protoChanged
();
propertyMap
.
protoChanged
(
false
);
}
}
listeners
.
clear
();
...
...
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java
浏览文件 @
b642e31e
此差异已折叠。
点击以展开。
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
浏览文件 @
b642e31e
...
...
@@ -368,8 +368,8 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
}
@Override
PropertyMap
getAllocatorMap
()
{
return
allocationStrategy
.
getAllocatorMap
();
PropertyMap
getAllocatorMap
(
final
ScriptObject
prototype
)
{
return
allocationStrategy
.
getAllocatorMap
(
prototype
);
}
@Override
...
...
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java
浏览文件 @
b642e31e
...
...
@@ -521,35 +521,39 @@ public class ScriptFunction extends ScriptObject {
assert
!
isBoundFunction
();
// allocate never invoked on bound functions
final
ScriptObject
object
=
data
.
allocate
(
getAllocatorMap
());
final
ScriptObject
prototype
=
getAllocatorPrototype
();
final
ScriptObject
object
=
data
.
allocate
(
getAllocatorMap
(
prototype
));
if
(
object
!=
null
)
{
final
Object
prototype
=
getPrototype
();
if
(
prototype
instanceof
ScriptObject
)
{
object
.
setInitialProto
((
ScriptObject
)
prototype
);
}
if
(
object
.
getProto
()
==
null
)
{
object
.
setInitialProto
(
getObjectPrototype
());
}
object
.
setInitialProto
(
prototype
);
}
return
object
;
}
private
PropertyMap
getAllocatorMap
()
{
if
(
allocatorMap
==
null
)
{
allocatorMap
=
data
.
getAllocatorMap
();
/**
* Get the property map used by "allocate"
* @param prototype actual prototype object
* @return property map
*/
private
synchronized
PropertyMap
getAllocatorMap
(
final
ScriptObject
prototype
)
{
if
(
allocatorMap
==
null
||
allocatorMap
.
isInvalidSharedMapFor
(
prototype
))
{
// The prototype map has changed since this function was last used as constructor.
// Get a new allocator map.
allocatorMap
=
data
.
getAllocatorMap
(
prototype
);
}
return
allocatorMap
;
}
/**
* Return Object.prototype - used by "allocate"
*
* @return Object.prototype
* Return the actual prototype used by "allocate"
* @return allocator prototype
*/
protected
final
ScriptObject
getObjectPrototype
()
{
private
ScriptObject
getAllocatorPrototype
()
{
final
Object
prototype
=
getPrototype
();
if
(
prototype
instanceof
ScriptObject
)
{
return
(
ScriptObject
)
prototype
;
}
return
Global
.
objectPrototype
();
}
...
...
@@ -591,10 +595,10 @@ public class ScriptFunction extends ScriptObject {
*
* @param newPrototype new prototype object
*/
public
final
void
setPrototype
(
final
Object
newPrototype
)
{
public
synchronized
final
void
setPrototype
(
final
Object
newPrototype
)
{
if
(
newPrototype
instanceof
ScriptObject
&&
newPrototype
!=
this
.
prototype
&&
allocatorMap
!=
null
)
{
//
Replace our current allocator map with one that is associated with
the new prototype.
allocatorMap
=
allocatorMap
.
changeProto
((
ScriptObject
)
newPrototype
)
;
//
Unset allocator map to be replaced with one matching
the new prototype.
allocatorMap
=
null
;
}
this
.
prototype
=
newPrototype
;
}
...
...
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunctionData.java
浏览文件 @
b642e31e
...
...
@@ -389,9 +389,10 @@ public abstract class ScriptFunctionData implements Serializable {
/**
* Get the property map to use for objects allocated by this function.
*
* @param prototype the prototype of the allocated object
* @return the property map for allocated objects.
*/
PropertyMap
getAllocatorMap
()
{
PropertyMap
getAllocatorMap
(
final
ScriptObject
prototype
)
{
return
null
;
}
...
...
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java
浏览文件 @
b642e31e
...
...
@@ -809,9 +809,11 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
if
(
deep
)
{
final
ScriptObject
myProto
=
getProto
();
if
(
myProto
!=
null
)
{
return
myProto
.
findProperty
(
key
,
deep
,
start
);
}
final
FindProperty
find
=
myProto
==
null
?
null
:
myProto
.
findProperty
(
key
,
true
,
start
);
// checkSharedProtoMap must be invoked after myProto.checkSharedProtoMap to propagate
// shared proto invalidation up the prototype chain. It also must be invoked when prototype is null.
checkSharedProtoMap
();
return
find
;
}
return
null
;
...
...
@@ -832,7 +834,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
if
(
deep
)
{
final
ScriptObject
myProto
=
getProto
();
if
(
myProto
!=
null
)
{
return
myProto
.
hasProperty
(
key
,
deep
);
return
myProto
.
hasProperty
(
key
,
true
);
}
}
...
...
@@ -1258,11 +1260,8 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
if
(
oldProto
!=
newProto
)
{
proto
=
newProto
;
// Let current listeners know that the prototype has changed and set our map
final
PropertyListeners
listeners
=
getMap
().
getListeners
();
if
(
listeners
!=
null
)
{
listeners
.
protoChanged
();
}
// Let current listeners know that the prototype has changed
getMap
().
protoChanged
(
true
);
// Replace our current allocator map with one that is associated with the new prototype.
setMap
(
getMap
().
changeProto
(
newProto
));
}
...
...
@@ -1314,7 +1313,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
}
p
=
p
.
getProto
();
}
setProto
((
ScriptObject
)
newProto
);
setProto
((
ScriptObject
)
newProto
);
}
else
{
throw
typeError
(
"cant.set.proto.to.non.object"
,
ScriptRuntime
.
safeToString
(
this
),
ScriptRuntime
.
safeToString
(
newProto
));
}
...
...
@@ -2012,11 +2011,11 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
final
ScriptObject
owner
=
find
.
getOwner
();
final
Class
<
ClassCastException
>
exception
=
explicitInstanceOfCheck
?
null
:
ClassCastException
.
class
;
final
SwitchPoint
protoSwitchPoint
;
final
SwitchPoint
[]
protoSwitchPoints
;
if
(
mh
==
null
)
{
mh
=
Lookup
.
emptyGetter
(
returnType
);
protoSwitchPoint
=
getProtoSwitchPoint
(
name
,
owner
);
protoSwitchPoint
s
=
getProtoSwitchPoints
(
name
,
owner
);
}
else
if
(!
find
.
isSelf
())
{
assert
mh
.
type
().
returnType
().
equals
(
returnType
)
:
"return type mismatch for getter "
+
mh
.
type
().
returnType
()
+
" != "
+
returnType
;
...
...
@@ -2024,12 +2023,12 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
// Add a filter that replaces the self object with the prototype owning the property.
mh
=
addProtoFilter
(
mh
,
find
.
getProtoChainLength
());
}
protoSwitchPoint
=
getProtoSwitchPoint
(
name
,
owner
);
protoSwitchPoint
s
=
getProtoSwitchPoints
(
name
,
owner
);
}
else
{
protoSwitchPoint
=
null
;
protoSwitchPoint
s
=
null
;
}
final
GuardedInvocation
inv
=
new
GuardedInvocation
(
mh
,
guard
,
protoSwitchPoint
,
exception
);
final
GuardedInvocation
inv
=
new
GuardedInvocation
(
mh
,
guard
,
protoSwitchPoint
s
,
exception
);
return
inv
.
addSwitchPoint
(
findBuiltinSwitchPoint
(
name
));
}
...
...
@@ -2128,17 +2127,32 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
* @param owner the property owner, null if property is not defined
* @return a SwitchPoint or null
*/
public
final
SwitchPoint
getProtoSwitchPoint
(
final
String
name
,
final
ScriptObject
owner
)
{
public
final
SwitchPoint
[]
getProtoSwitchPoints
(
final
String
name
,
final
ScriptObject
owner
)
{
if
(
owner
==
this
||
getProto
()
==
null
)
{
return
null
;
}
final
List
<
SwitchPoint
>
switchPoints
=
new
ArrayList
<>();
for
(
ScriptObject
obj
=
this
;
obj
!=
owner
&&
obj
.
getProto
()
!=
null
;
obj
=
obj
.
getProto
())
{
final
ScriptObject
parent
=
obj
.
getProto
();
parent
.
getMap
().
addListener
(
name
,
obj
.
getMap
());
final
SwitchPoint
sp
=
parent
.
getMap
().
getSharedProtoSwitchPoint
();
if
(
sp
!=
null
&&
!
sp
.
hasBeenInvalidated
())
{
switchPoints
.
add
(
sp
);
}
}
switchPoints
.
add
(
getMap
().
getSwitchPoint
(
name
));
return
switchPoints
.
toArray
(
new
SwitchPoint
[
switchPoints
.
size
()]);
}
return
getMap
().
getSwitchPoint
(
name
);
private
void
checkSharedProtoMap
()
{
// Check if our map has an expected shared prototype property map. If it has, make sure that
// the prototype map has not been invalidated, and that it does match the actual map of the prototype.
if
(
getMap
().
isInvalidSharedMapFor
(
getProto
()))
{
// Change our own map to one that does not assume a shared prototype map.
setMap
(
getMap
().
makeUnsharedCopy
());
}
}
/**
...
...
@@ -2220,7 +2234,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
return
new
GuardedInvocation
(
Lookup
.
EMPTY_SETTER
,
NashornGuards
.
getMapGuard
(
getMap
(),
explicitInstanceOfCheck
),
getProtoSwitchPoint
(
name
,
null
),
getProtoSwitchPoint
s
(
name
,
null
),
explicitInstanceOfCheck
?
null
:
ClassCastException
.
class
);
}
...
...
@@ -2366,7 +2380,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
find
.
getGetter
(
Object
.
class
,
INVALID_PROGRAM_POINT
,
request
),
find
.
getProtoChainLength
(),
func
),
getProtoSwitchPoint
(
NO_SUCH_PROPERTY_NAME
,
find
.
getOwner
()),
getProtoSwitchPoint
s
(
NO_SUCH_PROPERTY_NAME
,
find
.
getOwner
()),
//TODO this doesn't need a ClassCastException as guard always checks script object
null
);
}
...
...
@@ -2438,7 +2452,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
}
return
new
GuardedInvocation
(
Lookup
.
emptyGetter
(
desc
.
getMethodType
().
returnType
()),
NashornGuards
.
getMapGuard
(
getMap
(),
explicitInstanceOfCheck
),
getProtoSwitchPoint
(
name
,
null
),
NashornGuards
.
getMapGuard
(
getMap
(),
explicitInstanceOfCheck
),
getProtoSwitchPoint
s
(
name
,
null
),
explicitInstanceOfCheck
?
null
:
ClassCastException
.
class
);
}
...
...
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/SetMethodCreator.java
浏览文件 @
b642e31e
...
...
@@ -186,10 +186,7 @@ final class SetMethodCreator {
private
SetMethod
createNewPropertySetter
(
final
SwitchPoint
builtinSwitchPoint
)
{
final
SetMethod
sm
=
map
.
getFreeFieldSlot
()
>
-
1
?
createNewFieldSetter
(
builtinSwitchPoint
)
:
createNewSpillPropertySetter
(
builtinSwitchPoint
);
final
PropertyListeners
listeners
=
map
.
getListeners
();
if
(
listeners
!=
null
)
{
listeners
.
propertyAdded
(
sm
.
property
);
}
map
.
propertyAdded
(
sm
.
property
,
true
);
return
sm
;
}
...
...
@@ -204,7 +201,7 @@ final class SetMethodCreator {
//fast type specific setter
final
MethodHandle
fastSetter
=
property
.
getSetter
(
type
,
newMap
);
//0 sobj, 1 value, slot folded for spill property already
//slow setter, that calls ScriptObject.set with appropr
ai
te type and key name
//slow setter, that calls ScriptObject.set with appropr
ia
te type and key name
MethodHandle
slowSetter
=
ScriptObject
.
SET_SLOW
[
getAccessorTypeIndex
(
type
)];
slowSetter
=
MH
.
insertArguments
(
slowSetter
,
3
,
NashornCallSiteDescriptor
.
getFlags
(
desc
));
slowSetter
=
MH
.
insertArguments
(
slowSetter
,
1
,
name
);
...
...
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/SharedPropertyMap.java
0 → 100644
浏览文件 @
b642e31e
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package
jdk.nashorn.internal.runtime
;
import
java.lang.invoke.SwitchPoint
;
/**
* This class represents a property map that can be shared among multiple prototype objects, allowing all inheriting
* top-level objects to also share one property map. This is class is only used for prototype objects, the
* top-level objects use ordinary {@link PropertyMap}s with the {@link PropertyMap#sharedProtoMap} field
* set to the expected shared prototype map.
*
* <p>When an instance of this class is evolved because a property is added, removed, or modified in an object
* using it, the {@link #invalidateSwitchPoint()} method is invoked to signal to all callsites and inheriting
* objects that the assumption of a single shared prototype map is no longer valid. The property map resulting
* from the modification will no longer be an instance of this class.</p>
*/
public
final
class
SharedPropertyMap
extends
PropertyMap
{
private
SwitchPoint
switchPoint
;
private
static
final
long
serialVersionUID
=
2166297719721778876L
;
/**
* Create a new shared property map from the given {@code map}.
* @param map property map to copy
*/
public
SharedPropertyMap
(
final
PropertyMap
map
)
{
super
(
map
);
this
.
switchPoint
=
new
SwitchPoint
();
}
@Override
public
void
propertyAdded
(
final
Property
property
,
final
boolean
isSelf
)
{
if
(
isSelf
)
{
invalidateSwitchPoint
();
}
super
.
propertyAdded
(
property
,
isSelf
);
}
@Override
public
void
propertyDeleted
(
final
Property
property
,
final
boolean
isSelf
)
{
if
(
isSelf
)
{
invalidateSwitchPoint
();
}
super
.
propertyDeleted
(
property
,
isSelf
);
}
@Override
public
void
propertyModified
(
final
Property
oldProperty
,
final
Property
newProperty
,
final
boolean
isSelf
)
{
if
(
isSelf
)
{
invalidateSwitchPoint
();
}
super
.
propertyModified
(
oldProperty
,
newProperty
,
isSelf
);
}
@Override
synchronized
boolean
isValidSharedProtoMap
()
{
return
switchPoint
!=
null
;
}
@Override
synchronized
SwitchPoint
getSharedProtoSwitchPoint
()
{
return
switchPoint
;
}
/**
* Invalidate the shared prototype switch point if this is a shared prototype map.
*/
synchronized
void
invalidateSwitchPoint
()
{
if
(
switchPoint
!=
null
)
{
assert
!
switchPoint
.
hasBeenInvalidated
();
SwitchPoint
.
invalidateAll
(
new
SwitchPoint
[]{
switchPoint
});
switchPoint
=
null
;
}
}
}
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/WithObject.java
浏览文件 @
b642e31e
...
...
@@ -46,7 +46,7 @@ import jdk.nashorn.internal.runtime.linker.NashornGuards;
*
*/
public
final
class
WithObject
extends
Scope
{
private
static
final
MethodHandle
WITHEXPRESSIONGUARD
=
findOwnMH
(
"withExpressionGuard"
,
boolean
.
class
,
Object
.
class
,
PropertyMap
.
class
,
SwitchPoint
.
class
);
private
static
final
MethodHandle
WITHEXPRESSIONGUARD
=
findOwnMH
(
"withExpressionGuard"
,
boolean
.
class
,
Object
.
class
,
PropertyMap
.
class
,
SwitchPoint
[]
.
class
);
private
static
final
MethodHandle
WITHEXPRESSIONFILTER
=
findOwnMH
(
"withFilterExpression"
,
Object
.
class
,
Object
.
class
);
private
static
final
MethodHandle
WITHSCOPEFILTER
=
findOwnMH
(
"withFilterScope"
,
Object
.
class
,
Object
.
class
);
private
static
final
MethodHandle
BIND_TO_EXPRESSION_OBJ
=
findOwnMH
(
"bindToExpression"
,
Object
.
class
,
Object
.
class
,
Object
.
class
);
...
...
@@ -360,13 +360,24 @@ public final class WithObject extends Scope {
private
MethodHandle
expressionGuard
(
final
String
name
,
final
ScriptObject
owner
)
{
final
PropertyMap
map
=
expression
.
getMap
();
final
SwitchPoint
sp
=
expression
.
getProtoSwitchPoint
(
name
,
owner
);
final
SwitchPoint
[]
sp
=
expression
.
getProtoSwitchPoints
(
name
,
owner
);
return
MH
.
insertArguments
(
WITHEXPRESSIONGUARD
,
1
,
map
,
sp
);
}
@SuppressWarnings
(
"unused"
)
private
static
boolean
withExpressionGuard
(
final
Object
receiver
,
final
PropertyMap
map
,
final
SwitchPoint
sp
)
{
return
((
WithObject
)
receiver
).
expression
.
getMap
()
==
map
&&
(
sp
==
null
||
!
sp
.
hasBeenInvalidated
());
private
static
boolean
withExpressionGuard
(
final
Object
receiver
,
final
PropertyMap
map
,
final
SwitchPoint
[]
sp
)
{
return
((
WithObject
)
receiver
).
expression
.
getMap
()
==
map
&&
!
hasBeenInvalidated
(
sp
);
}
private
static
boolean
hasBeenInvalidated
(
final
SwitchPoint
[]
switchPoints
)
{
if
(
switchPoints
!=
null
)
{
for
(
final
SwitchPoint
switchPoint
:
switchPoints
)
{
if
(
switchPoint
.
hasBeenInvalidated
())
{
return
true
;
}
}
}
return
false
;
}
/**
...
...
nashorn/test/script/basic/JDK-8134569.js
浏览文件 @
b642e31e
...
...
@@ -62,67 +62,146 @@ function createDeep() {
return
new
C
();
}
function
createDeeper
()
{
function
C
()
{
this
.
i1
=
1
;
this
.
i2
=
2
;
this
.
i3
=
3
;
return
this
;
}
function
D
()
{
this
.
p1
=
1
;
this
.
p2
=
2
;
this
.
p3
=
3
;
return
this
;
}
function
E
()
{
this
.
e1
=
1
;
this
.
e2
=
2
;
this
.
e3
=
3
;
return
this
;
}
D
.
prototype
=
new
E
();
C
.
prototype
=
new
D
();
return
new
C
();
}
function
createEval
()
{
return
eval
(
"
Object.create({})
"
);
}
function
p
(
o
)
{
print
(
o
.
x
)
}
var
a
,
b
;
function
e
(
o
)
{
print
(
o
.
e1
)
}
var
a
,
b
,
c
;
create
();
a
=
create
();
b
=
create
();
c
=
create
();
a
.
__proto__
.
x
=
123
;
p
(
a
);
p
(
b
);
p
(
c
);
a
=
create
();
b
=
create
();
c
=
create
();
b
.
__proto__
.
x
=
123
;
p
(
a
);
p
(
b
);
p
(
c
);
a
=
createEmpty
();
b
=
createEmpty
();
c
=
createEmpty
();
a
.
__proto__
.
x
=
123
;
p
(
a
);
p
(
b
);
p
(
c
);
a
=
createEmpty
();
b
=
createEmpty
();
c
=
createEmpty
();
b
.
__proto__
.
x
=
123
;
p
(
a
);
p
(
b
);
p
(
c
);
a
=
createDeep
();
b
=
createDeep
();
c
=
createDeep
();
a
.
__proto__
.
__proto__
.
x
=
123
;
p
(
a
);
p
(
b
);
p
(
c
);
a
=
createDeep
();
b
=
createDeep
();
c
=
createDeep
();
b
.
__proto__
.
__proto__
.
x
=
123
;
p
(
a
);
p
(
b
);
p
(
c
);
a
=
createDeeper
();
b
=
createDeeper
();
c
=
createDeeper
();
a
.
__proto__
.
__proto__
.
__proto__
.
x
=
123
;
p
(
a
);
p
(
b
);
p
(
c
);
a
=
createDeeper
();
b
=
createDeeper
();
c
=
createDeeper
();
b
.
__proto__
.
__proto__
.
__proto__
.
x
=
123
;
p
(
a
);
p
(
b
);
p
(
c
);
a
=
createDeeper
();
b
=
createDeeper
();
c
=
createDeeper
();
a
.
__proto__
.
__proto__
=
null
;
e
(
a
);
e
(
b
);
e
(
c
);
a
=
createDeeper
();
b
=
createDeeper
();
c
=
createDeeper
();
b
.
__proto__
.
__proto__
=
null
;
e
(
a
);
e
(
b
);
e
(
c
);
a
=
createEval
();
b
=
createEval
();
c
=
createEval
();
a
.
__proto__
.
x
=
123
;
p
(
a
);
p
(
b
);
p
(
c
);
a
=
createEval
();
b
=
createEval
();
c
=
createEval
();
b
.
__proto__
.
x
=
123
;
p
(
a
);
p
(
b
);
p
(
c
);
nashorn/test/script/basic/JDK-8134569.js.EXPECTED
浏览文件 @
b642e31e
123
undefined
undefined
undefined
123
undefined
123
undefined
undefined
undefined
123
undefined
123
undefined
undefined
undefined
123
undefined
123
undefined
undefined
undefined
123
undefined
undefined
1
1
1
undefined
1
123
undefined
undefined
undefined
123
undefined
nashorn/test/script/basic/JDK-8134609.js
0 → 100644
浏览文件 @
b642e31e
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* JDK-8134609: Allow constructors with same prototoype map to share the allocator map
*
* @test
* @run
* @fork
* @option -Dnashorn.debug
*/
function
createProto
(
members
)
{
function
P
()
{
for
(
var
id
in
members
)
{
if
(
members
.
hasOwnProperty
(
id
))
{
this
[
id
]
=
members
[
id
];
}
}
return
this
;
}
return
new
P
();
}
function
createSubclass
(
prototype
,
members
)
{
function
C
()
{
for
(
var
id
in
members
)
{
if
(
members
.
hasOwnProperty
(
id
))
{
this
[
id
]
=
members
[
id
];
}
}
return
this
;
}
C
.
prototype
=
prototype
;
return
new
C
();
}
function
assertP1
(
object
,
value
)
{
Assert
.
assertTrue
(
object
.
p1
===
value
);
}
// First prototype will have non-shared proto-map. Second and third will be shared.
var
proto0
=
createProto
({
p1
:
0
,
p2
:
1
});
var
proto1
=
createProto
({
p1
:
1
,
p2
:
2
});
var
proto2
=
createProto
({
p1
:
2
,
p2
:
3
});
Assert
.
assertTrue
(
Debug
.
map
(
proto1
)
===
Debug
.
map
(
proto2
));
assertP1
(
proto1
,
1
);
assertP1
(
proto2
,
2
);
// First instantiation will have a non-shared prototype map, from the second one
// maps will be shared until a different proto map comes along.
var
child0
=
createSubclass
(
proto1
,
{
c1
:
1
,
c2
:
2
});
var
child1
=
createSubclass
(
proto2
,
{
c1
:
2
,
c2
:
3
});
var
child2
=
createSubclass
(
proto1
,
{
c1
:
3
,
c2
:
4
});
var
child3
=
createSubclass
(
proto2
,
{
c1
:
1
,
c2
:
2
});
var
child4
=
createSubclass
(
proto0
,
{
c1
:
3
,
c2
:
2
});
Assert
.
assertTrue
(
Debug
.
map
(
child1
)
===
Debug
.
map
(
child2
));
Assert
.
assertTrue
(
Debug
.
map
(
child1
)
===
Debug
.
map
(
child3
));
Assert
.
assertTrue
(
Debug
.
map
(
child3
)
!==
Debug
.
map
(
child4
));
assertP1
(
child1
,
2
);
assertP1
(
child2
,
1
);
assertP1
(
child3
,
2
);
assertP1
(
child4
,
0
);
Assert
.
assertTrue
(
delete
proto2
.
p1
);
assertP1
(
child3
,
undefined
);
assertP1
(
child2
,
1
);
Assert
.
assertTrue
(
Debug
.
map
(
child1
)
!==
Debug
.
map
(
child3
));
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录