Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
567a6555
D
dragonwell8_hotspot
项目概览
openanolis
/
dragonwell8_hotspot
通知
2
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_hotspot
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
567a6555
编写于
7月 09, 2013
作者:
A
acorn
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
b339fe4c
54149f32
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
426 addition
and
165 deletion
+426
-165
src/share/vm/classfile/defaultMethods.cpp
src/share/vm/classfile/defaultMethods.cpp
+423
-165
src/share/vm/runtime/globals.hpp
src/share/vm/runtime/globals.hpp
+3
-0
未找到文件。
src/share/vm/classfile/defaultMethods.cpp
浏览文件 @
567a6555
...
@@ -318,17 +318,17 @@ class KeepAliveVisitor : public HierarchyVisitor<KeepAliveVisitor> {
...
@@ -318,17 +318,17 @@ class KeepAliveVisitor : public HierarchyVisitor<KeepAliveVisitor> {
}
}
};
};
// A method family contains a set of all methods that implement a single
// A method family contains a set of all methods that implement a single
// language-level method. Because of erasure, these methods may have different
// erased method. As members of the set are collected while walking over the
// signatures. As members of the set are collected while walking over the
// hierarchy, they are tagged with a qualification state. The qualification
// hierarchy, they are tagged with a qualification state. The qualification
// state for an erased method is set to disqualified if there exists a path
// state for an erased method is set to disqualified if there exists a path
// from the root of hierarchy to the method that contains an interleaving
// from the root of hierarchy to the method that contains an interleaving
// language-equivalent method defined in an interface.
// erased method defined in an interface.
class
MethodFamily
:
public
ResourceObj
{
class
MethodFamily
:
public
ResourceObj
{
private:
private:
generic
::
MethodDescriptor
*
_descriptor
;
// language-level description
GrowableArray
<
Pair
<
Method
*
,
QualifiedState
>
>
_members
;
GrowableArray
<
Pair
<
Method
*
,
QualifiedState
>
>
_members
;
ResourceHashtable
<
Method
*
,
int
>
_member_index
;
ResourceHashtable
<
Method
*
,
int
>
_member_index
;
...
@@ -358,15 +358,8 @@ class MethodFamily : public ResourceObj {
...
@@ -358,15 +358,8 @@ class MethodFamily : public ResourceObj {
public:
public:
MethodFamily
(
generic
::
MethodDescriptor
*
canonical_desc
)
MethodFamily
()
:
_descriptor
(
canonical_desc
),
_selected_target
(
NULL
),
:
_selected_target
(
NULL
),
_exception_message
(
NULL
)
{}
_exception_message
(
NULL
)
{}
generic
::
MethodDescriptor
*
descriptor
()
const
{
return
_descriptor
;
}
bool
descriptor_matches
(
generic
::
MethodDescriptor
*
md
,
generic
::
Context
*
ctx
)
{
return
descriptor
()
->
covariant_match
(
md
,
ctx
);
}
void
set_target_if_empty
(
Method
*
m
)
{
void
set_target_if_empty
(
Method
*
m
)
{
if
(
_selected_target
==
NULL
&&
!
m
->
is_overpass
())
{
if
(
_selected_target
==
NULL
&&
!
m
->
is_overpass
())
{
...
@@ -441,16 +434,10 @@ class MethodFamily : public ResourceObj {
...
@@ -441,16 +434,10 @@ class MethodFamily : public ResourceObj {
}
}
#ifndef PRODUCT
#ifndef PRODUCT
void
print_on
(
outputStream
*
str
)
const
{
void
print_sig_on
(
outputStream
*
str
,
Symbol
*
signature
,
int
indent
)
const
{
print_on
(
str
,
0
);
}
void
print_on
(
outputStream
*
str
,
int
indent
)
const
{
streamIndentor
si
(
str
,
indent
*
2
);
streamIndentor
si
(
str
,
indent
*
2
);
generic
::
Context
ctx
(
NULL
);
// empty, as _descriptor already canonicalized
str
->
indent
().
print_cr
(
"Logical Method %s:"
,
signature
->
as_C_string
());
TempNewSymbol
family
=
descriptor
()
->
reify_signature
(
&
ctx
,
Thread
::
current
());
str
->
indent
().
print_cr
(
"Logical Method %s:"
,
family
->
as_C_string
());
streamIndentor
si2
(
str
);
streamIndentor
si2
(
str
);
for
(
int
i
=
0
;
i
<
_members
.
length
();
++
i
)
{
for
(
int
i
=
0
;
i
<
_members
.
length
();
++
i
)
{
...
@@ -516,38 +503,94 @@ Symbol* MethodFamily::generate_conflicts_message(GrowableArray<Method*>* methods
...
@@ -516,38 +503,94 @@ Symbol* MethodFamily::generate_conflicts_message(GrowableArray<Method*>* methods
return
SymbolTable
::
new_symbol
(
ss
.
base
(),
(
int
)
ss
.
size
(),
CHECK_NULL
);
return
SymbolTable
::
new_symbol
(
ss
.
base
(),
(
int
)
ss
.
size
(),
CHECK_NULL
);
}
}
// A generic method family contains a set of all methods that implement a single
// language-level method. Because of erasure, these methods may have different
// signatures. As members of the set are collected while walking over the
// hierarchy, they are tagged with a qualification state. The qualification
// state for an erased method is set to disqualified if there exists a path
// from the root of hierarchy to the method that contains an interleaving
// language-equivalent method defined in an interface.
class
GenericMethodFamily
:
public
MethodFamily
{
private:
generic
::
MethodDescriptor
*
_descriptor
;
// language-level description
public:
GenericMethodFamily
(
generic
::
MethodDescriptor
*
canonical_desc
)
:
_descriptor
(
canonical_desc
)
{}
generic
::
MethodDescriptor
*
descriptor
()
const
{
return
_descriptor
;
}
bool
descriptor_matches
(
generic
::
MethodDescriptor
*
md
,
generic
::
Context
*
ctx
)
{
return
descriptor
()
->
covariant_match
(
md
,
ctx
);
}
#ifndef PRODUCT
Symbol
*
get_generic_sig
()
const
{
generic
::
Context
ctx
(
NULL
);
// empty, as _descriptor already canonicalized
TempNewSymbol
sig
=
descriptor
()
->
reify_signature
(
&
ctx
,
Thread
::
current
());
return
sig
;
}
#endif // ndef PRODUCT
};
class
StateRestorer
;
class
StateRestorer
;
// StatefulMethodFamily is a wrapper around MethodFamily that maintains the
// StatefulMethodFamily is a wrapper around
a
MethodFamily that maintains the
// qualification state during hierarchy visitation, and applies that state
// qualification state during hierarchy visitation, and applies that state
// when adding members to the MethodFamily
.
// when adding members to the MethodFamily
class
StatefulMethodFamily
:
public
ResourceObj
{
class
StatefulMethodFamily
:
public
ResourceObj
{
friend
class
StateRestorer
;
friend
class
StateRestorer
;
private:
private:
MethodFamily
*
_method
;
QualifiedState
_qualification_state
;
QualifiedState
_qualification_state
;
void
set_qualification_state
(
QualifiedState
state
)
{
void
set_qualification_state
(
QualifiedState
state
)
{
_qualification_state
=
state
;
_qualification_state
=
state
;
}
}
protected:
MethodFamily
*
_method_family
;
public:
public:
StatefulMethodFamily
(
generic
::
MethodDescriptor
*
md
,
generic
::
Context
*
ctx
)
{
StatefulMethodFamily
()
{
_method
=
new
MethodFamily
(
md
->
canonicalize
(
ctx
)
);
_method_family
=
new
MethodFamily
(
);
_qualification_state
=
QUALIFIED
;
_qualification_state
=
QUALIFIED
;
}
}
void
set_target_if_empty
(
Method
*
m
)
{
_method
->
set_target_if_empty
(
m
);
}
StatefulMethodFamily
(
MethodFamily
*
mf
)
{
_method_family
=
mf
;
_qualification_state
=
QUALIFIED
;
}
MethodFamily
*
get_method_family
()
{
return
_method
;
}
void
set_target_if_empty
(
Method
*
m
)
{
_method_family
->
set_target_if_empty
(
m
)
;
}
bool
descriptor_matches
(
generic
::
MethodDescriptor
*
md
,
generic
::
Context
*
ctx
)
{
MethodFamily
*
get_method_family
()
{
return
_method_family
;
}
return
_method
->
descriptor_matches
(
md
,
ctx
);
}
StateRestorer
*
record_method_and_dq_further
(
Method
*
mo
);
StateRestorer
*
record_method_and_dq_further
(
Method
*
mo
);
};
};
// StatefulGenericMethodFamily is a wrapper around GenericMethodFamily that maintains the
// qualification state during hierarchy visitation, and applies that state
// when adding members to the GenericMethodFamily.
class
StatefulGenericMethodFamily
:
public
StatefulMethodFamily
{
public:
StatefulGenericMethodFamily
(
generic
::
MethodDescriptor
*
md
,
generic
::
Context
*
ctx
)
:
StatefulMethodFamily
(
new
GenericMethodFamily
(
md
->
canonicalize
(
ctx
)))
{
}
GenericMethodFamily
*
get_method_family
()
{
return
(
GenericMethodFamily
*
)
_method_family
;
}
bool
descriptor_matches
(
generic
::
MethodDescriptor
*
md
,
generic
::
Context
*
ctx
)
{
return
get_method_family
()
->
descriptor_matches
(
md
,
ctx
);
}
};
class
StateRestorer
:
public
PseudoScopeMark
{
class
StateRestorer
:
public
PseudoScopeMark
{
private:
private:
StatefulMethodFamily
*
_method
;
StatefulMethodFamily
*
_method
;
...
@@ -563,9 +606,9 @@ class StateRestorer : public PseudoScopeMark {
...
@@ -563,9 +606,9 @@ class StateRestorer : public PseudoScopeMark {
StateRestorer
*
StatefulMethodFamily
::
record_method_and_dq_further
(
Method
*
mo
)
{
StateRestorer
*
StatefulMethodFamily
::
record_method_and_dq_further
(
Method
*
mo
)
{
StateRestorer
*
mark
=
new
StateRestorer
(
this
,
_qualification_state
);
StateRestorer
*
mark
=
new
StateRestorer
(
this
,
_qualification_state
);
if
(
_qualification_state
==
QUALIFIED
)
{
if
(
_qualification_state
==
QUALIFIED
)
{
_method
->
record_qualified_method
(
mo
);
_method
_family
->
record_qualified_method
(
mo
);
}
else
{
}
else
{
_method
->
record_disqualified_method
(
mo
);
_method
_family
->
record_disqualified_method
(
mo
);
}
}
// Everything found "above"??? this method in the hierarchy walk is set to
// Everything found "above"??? this method in the hierarchy walk is set to
// disqualified
// disqualified
...
@@ -573,15 +616,15 @@ StateRestorer* StatefulMethodFamily::record_method_and_dq_further(Method* mo) {
...
@@ -573,15 +616,15 @@ StateRestorer* StatefulMethodFamily::record_method_and_dq_further(Method* mo) {
return
mark
;
return
mark
;
}
}
class
StatefulMethodFamilies
:
public
ResourceObj
{
class
Stateful
Generic
MethodFamilies
:
public
ResourceObj
{
private:
private:
GrowableArray
<
StatefulMethodFamily
*>
_methods
;
GrowableArray
<
Stateful
Generic
MethodFamily
*>
_methods
;
public:
public:
StatefulMethodFamily
*
find_matching
(
Stateful
Generic
MethodFamily
*
find_matching
(
generic
::
MethodDescriptor
*
md
,
generic
::
Context
*
ctx
)
{
generic
::
MethodDescriptor
*
md
,
generic
::
Context
*
ctx
)
{
for
(
int
i
=
0
;
i
<
_methods
.
length
();
++
i
)
{
for
(
int
i
=
0
;
i
<
_methods
.
length
();
++
i
)
{
StatefulMethodFamily
*
existing
=
_methods
.
at
(
i
);
Stateful
Generic
MethodFamily
*
existing
=
_methods
.
at
(
i
);
if
(
existing
->
descriptor_matches
(
md
,
ctx
))
{
if
(
existing
->
descriptor_matches
(
md
,
ctx
))
{
return
existing
;
return
existing
;
}
}
...
@@ -589,17 +632,17 @@ class StatefulMethodFamilies : public ResourceObj {
...
@@ -589,17 +632,17 @@ class StatefulMethodFamilies : public ResourceObj {
return
NULL
;
return
NULL
;
}
}
StatefulMethodFamily
*
find_matching_or_create
(
Stateful
Generic
MethodFamily
*
find_matching_or_create
(
generic
::
MethodDescriptor
*
md
,
generic
::
Context
*
ctx
)
{
generic
::
MethodDescriptor
*
md
,
generic
::
Context
*
ctx
)
{
StatefulMethodFamily
*
method
=
find_matching
(
md
,
ctx
);
Stateful
Generic
MethodFamily
*
method
=
find_matching
(
md
,
ctx
);
if
(
method
==
NULL
)
{
if
(
method
==
NULL
)
{
method
=
new
StatefulMethodFamily
(
md
,
ctx
);
method
=
new
Stateful
Generic
MethodFamily
(
md
,
ctx
);
_methods
.
append
(
method
);
_methods
.
append
(
method
);
}
}
return
method
;
return
method
;
}
}
void
extract_families_into
(
GrowableArray
<
MethodFamily
*>*
array
)
{
void
extract_families_into
(
GrowableArray
<
Generic
MethodFamily
*>*
array
)
{
for
(
int
i
=
0
;
i
<
_methods
.
length
();
++
i
)
{
for
(
int
i
=
0
;
i
<
_methods
.
length
();
++
i
)
{
array
->
append
(
_methods
.
at
(
i
)
->
get_method_family
());
array
->
append
(
_methods
.
at
(
i
)
->
get_method_family
());
}
}
...
@@ -683,26 +726,79 @@ static GrowableArray<EmptyVtableSlot*>* find_empty_vtable_slots(
...
@@ -683,26 +726,79 @@ static GrowableArray<EmptyVtableSlot*>* find_empty_vtable_slots(
return
slots
;
return
slots
;
}
}
// Iterates over the superinterface type hierarchy looking for all methods
// with a specific erased signature.
class
FindMethodsByErasedSig
:
public
HierarchyVisitor
<
FindMethodsByErasedSig
>
{
private:
// Context data
Symbol
*
_method_name
;
Symbol
*
_method_signature
;
StatefulMethodFamily
*
_family
;
public:
FindMethodsByErasedSig
(
Symbol
*
name
,
Symbol
*
signature
)
:
_method_name
(
name
),
_method_signature
(
signature
),
_family
(
NULL
)
{}
void
get_discovered_family
(
MethodFamily
**
family
)
{
if
(
_family
!=
NULL
)
{
*
family
=
_family
->
get_method_family
();
}
else
{
*
family
=
NULL
;
}
}
void
*
new_node_data
(
InstanceKlass
*
cls
)
{
return
new
PseudoScope
();
}
void
free_node_data
(
void
*
node_data
)
{
PseudoScope
::
cast
(
node_data
)
->
destroy
();
}
// Find all methods on this hierarchy that match this
// method's erased (name, signature)
bool
visit
()
{
PseudoScope
*
scope
=
PseudoScope
::
cast
(
current_data
());
InstanceKlass
*
iklass
=
current_class
();
Method
*
m
=
iklass
->
find_method
(
_method_name
,
_method_signature
);
if
(
m
!=
NULL
)
{
if
(
_family
==
NULL
)
{
_family
=
new
StatefulMethodFamily
();
}
if
(
iklass
->
is_interface
())
{
StateRestorer
*
restorer
=
_family
->
record_method_and_dq_further
(
m
);
scope
->
add_mark
(
restorer
);
}
else
{
// This is the rule that methods in classes "win" (bad word) over
// methods in interfaces. This works because of single inheritance
_family
->
set_target_if_empty
(
m
);
}
}
return
true
;
}
};
// Iterates over the type hierarchy looking for all methods with a specific
// Iterates over the type hierarchy looking for all methods with a specific
// method name. The result of this is a set of method families each of
// method name. The result of this is a set of method families each of
// which is populated with a set of methods that implement the same
// which is populated with a set of methods that implement the same
// language-level signature.
// language-level signature.
class
FindMethodsBy
Name
:
public
HierarchyVisitor
<
FindMethodsByName
>
{
class
FindMethodsBy
GenericSig
:
public
HierarchyVisitor
<
FindMethodsByGenericSig
>
{
private:
private:
// Context data
// Context data
Thread
*
THREAD
;
Thread
*
THREAD
;
generic
::
DescriptorCache
*
_cache
;
generic
::
DescriptorCache
*
_cache
;
Symbol
*
_method_name
;
Symbol
*
_method_name
;
generic
::
Context
*
_ctx
;
generic
::
Context
*
_ctx
;
StatefulMethodFamilies
_families
;
Stateful
Generic
MethodFamilies
_families
;
public:
public:
FindMethodsBy
Name
(
generic
::
DescriptorCache
*
cache
,
Symbol
*
name
,
FindMethodsBy
GenericSig
(
generic
::
DescriptorCache
*
cache
,
Symbol
*
name
,
generic
::
Context
*
ctx
,
Thread
*
thread
)
:
generic
::
Context
*
ctx
,
Thread
*
thread
)
:
_cache
(
cache
),
_method_name
(
name
),
_ctx
(
ctx
),
THREAD
(
thread
)
{}
_cache
(
cache
),
_method_name
(
name
),
_ctx
(
ctx
),
THREAD
(
thread
)
{}
void
get_discovered_families
(
GrowableArray
<
MethodFamily
*>*
methods
)
{
void
get_discovered_families
(
GrowableArray
<
Generic
MethodFamily
*>*
methods
)
{
_families
.
extract_families_into
(
methods
);
_families
.
extract_families_into
(
methods
);
}
}
...
@@ -733,7 +829,7 @@ class FindMethodsByName : public HierarchyVisitor<FindMethodsByName> {
...
@@ -733,7 +829,7 @@ class FindMethodsByName : public HierarchyVisitor<FindMethodsByName> {
// Find all methods on this hierarchy that match this method
// Find all methods on this hierarchy that match this method
// (name, signature). This class collects other families of this
// (name, signature). This class collects other families of this
// method name.
// method name.
StatefulMethodFamily
*
family
=
Stateful
Generic
MethodFamily
*
family
=
_families
.
find_matching_or_create
(
md
,
_ctx
);
_families
.
find_matching_or_create
(
md
,
_ctx
);
if
(
klass
->
is_interface
())
{
if
(
klass
->
is_interface
())
{
...
@@ -752,8 +848,8 @@ class FindMethodsByName : public HierarchyVisitor<FindMethodsByName> {
...
@@ -752,8 +848,8 @@ class FindMethodsByName : public HierarchyVisitor<FindMethodsByName> {
};
};
#ifndef PRODUCT
#ifndef PRODUCT
static
void
print_families
(
static
void
print_
generic_
families
(
GrowableArray
<
MethodFamily
*>*
methods
,
Symbol
*
match
)
{
GrowableArray
<
Generic
MethodFamily
*>*
methods
,
Symbol
*
match
)
{
streamIndentor
si
(
tty
,
4
);
streamIndentor
si
(
tty
,
4
);
if
(
methods
->
length
()
==
0
)
{
if
(
methods
->
length
()
==
0
)
{
tty
->
indent
();
tty
->
indent
();
...
@@ -761,22 +857,87 @@ static void print_families(
...
@@ -761,22 +857,87 @@ static void print_families(
}
}
for
(
int
i
=
0
;
i
<
methods
->
length
();
++
i
)
{
for
(
int
i
=
0
;
i
<
methods
->
length
();
++
i
)
{
tty
->
indent
();
tty
->
indent
();
MethodFamily
*
lm
=
methods
->
at
(
i
);
Generic
MethodFamily
*
lm
=
methods
->
at
(
i
);
if
(
lm
->
contains_signature
(
match
))
{
if
(
lm
->
contains_signature
(
match
))
{
tty
->
print_cr
(
"<Matching>"
);
tty
->
print_cr
(
"<Matching>"
);
}
else
{
}
else
{
tty
->
print_cr
(
"<Non-Matching>"
);
tty
->
print_cr
(
"<Non-Matching>"
);
}
}
lm
->
print_
on
(
tty
,
1
);
lm
->
print_
sig_on
(
tty
,
lm
->
get_generic_sig
()
,
1
);
}
}
}
}
#endif // ndef PRODUCT
#endif // ndef PRODUCT
static
void
merge_in_new_methods
(
InstanceKlass
*
klass
,
GrowableArray
<
Method
*>*
new_methods
,
TRAPS
);
static
void
create_overpasses
(
static
void
create_overpasses
(
GrowableArray
<
EmptyVtableSlot
*>*
slots
,
InstanceKlass
*
klass
,
TRAPS
);
GrowableArray
<
EmptyVtableSlot
*>*
slots
,
InstanceKlass
*
klass
,
TRAPS
);
static
void
generate_generic_defaults
(
InstanceKlass
*
klass
,
GrowableArray
<
EmptyVtableSlot
*>*
empty_slots
,
EmptyVtableSlot
*
slot
,
int
current_slot_index
,
TRAPS
)
{
if
(
slot
->
is_bound
())
{
#ifndef PRODUCT
if
(
TraceDefaultMethods
)
{
streamIndentor
si
(
tty
,
4
);
tty
->
indent
().
print_cr
(
"Already bound to logical method:"
);
GenericMethodFamily
*
lm
=
(
GenericMethodFamily
*
)(
slot
->
get_binding
());
lm
->
print_sig_on
(
tty
,
lm
->
get_generic_sig
(),
1
);
}
#endif // ndef PRODUCT
return
;
// covered by previous processing
}
generic
::
DescriptorCache
cache
;
generic
::
Context
ctx
(
&
cache
);
FindMethodsByGenericSig
visitor
(
&
cache
,
slot
->
name
(),
&
ctx
,
CHECK
);
visitor
.
run
(
klass
);
GrowableArray
<
GenericMethodFamily
*>
discovered_families
;
visitor
.
get_discovered_families
(
&
discovered_families
);
#ifndef PRODUCT
if
(
TraceDefaultMethods
)
{
print_generic_families
(
&
discovered_families
,
slot
->
signature
());
}
#endif // ndef PRODUCT
// Find and populate any other slots that match the discovered families
for
(
int
j
=
current_slot_index
;
j
<
empty_slots
->
length
();
++
j
)
{
EmptyVtableSlot
*
open_slot
=
empty_slots
->
at
(
j
);
if
(
slot
->
name
()
==
open_slot
->
name
())
{
for
(
int
k
=
0
;
k
<
discovered_families
.
length
();
++
k
)
{
GenericMethodFamily
*
lm
=
discovered_families
.
at
(
k
);
if
(
lm
->
contains_signature
(
open_slot
->
signature
()))
{
lm
->
determine_target
(
klass
,
CHECK
);
open_slot
->
bind_family
(
lm
);
}
}
}
}
}
static
void
generate_erased_defaults
(
InstanceKlass
*
klass
,
GrowableArray
<
EmptyVtableSlot
*>*
empty_slots
,
EmptyVtableSlot
*
slot
,
TRAPS
)
{
// sets up a set of methods with the same exact erased signature
FindMethodsByErasedSig
visitor
(
slot
->
name
(),
slot
->
signature
());
visitor
.
run
(
klass
);
MethodFamily
*
family
;
visitor
.
get_discovered_family
(
&
family
);
if
(
family
!=
NULL
)
{
family
->
determine_target
(
klass
,
CHECK
);
slot
->
bind_family
(
family
);
}
}
static
void
merge_in_new_methods
(
InstanceKlass
*
klass
,
GrowableArray
<
Method
*>*
new_methods
,
TRAPS
);
// This is the guts of the default methods implementation. This is called just
// This is the guts of the default methods implementation. This is called just
// after the classfile has been parsed if some ancestor has default methods.
// after the classfile has been parsed if some ancestor has default methods.
//
//
...
@@ -807,8 +968,6 @@ void DefaultMethods::generate_default_methods(
...
@@ -807,8 +968,6 @@ void DefaultMethods::generate_default_methods(
// whatever scope it's in.
// whatever scope it's in.
ResourceMark
rm
(
THREAD
);
ResourceMark
rm
(
THREAD
);
generic
::
DescriptorCache
cache
;
// Keep entire hierarchy alive for the duration of the computation
// Keep entire hierarchy alive for the duration of the computation
KeepAliveRegistrar
keepAlive
(
THREAD
);
KeepAliveRegistrar
keepAlive
(
THREAD
);
KeepAliveVisitor
loadKeepAlive
(
&
keepAlive
);
KeepAliveVisitor
loadKeepAlive
(
&
keepAlive
);
...
@@ -837,47 +996,13 @@ void DefaultMethods::generate_default_methods(
...
@@ -837,47 +996,13 @@ void DefaultMethods::generate_default_methods(
tty
->
print_cr
(
""
);
tty
->
print_cr
(
""
);
}
}
#endif // ndef PRODUCT
#endif // ndef PRODUCT
if
(
slot
->
is_bound
())
{
#ifndef PRODUCT
if
(
TraceDefaultMethods
)
{
streamIndentor
si
(
tty
,
4
);
tty
->
indent
().
print_cr
(
"Already bound to logical method:"
);
slot
->
get_binding
()
->
print_on
(
tty
,
1
);
}
#endif // ndef PRODUCT
continue
;
// covered by previous processing
}
generic
::
Context
ctx
(
&
cache
);
FindMethodsByName
visitor
(
&
cache
,
slot
->
name
(),
&
ctx
,
CHECK
);
visitor
.
run
(
klass
);
GrowableArray
<
MethodFamily
*>
discovered_families
;
visitor
.
get_discovered_families
(
&
discovered_families
);
#ifndef PRODUCT
if
(
TraceDefaultMethods
)
{
print_families
(
&
discovered_families
,
slot
->
signature
());
}
#endif // ndef PRODUCT
// Find and populate any other slots that match the discovered families
if
(
ParseGenericDefaults
)
{
for
(
int
j
=
i
;
j
<
empty_slots
->
length
();
++
j
)
{
generate_generic_defaults
(
klass
,
empty_slots
,
slot
,
i
,
CHECK
);
EmptyVtableSlot
*
open_slot
=
empty_slots
->
at
(
j
);
}
else
{
generate_erased_defaults
(
klass
,
empty_slots
,
slot
,
CHECK
);
if
(
slot
->
name
()
==
open_slot
->
name
())
{
for
(
int
k
=
0
;
k
<
discovered_families
.
length
();
++
k
)
{
MethodFamily
*
lm
=
discovered_families
.
at
(
k
);
if
(
lm
->
contains_signature
(
open_slot
->
signature
()))
{
lm
->
determine_target
(
klass
,
CHECK
);
open_slot
->
bind_family
(
lm
);
}
}
}
}
}
}
}
#ifndef PRODUCT
#ifndef PRODUCT
if
(
TraceDefaultMethods
)
{
if
(
TraceDefaultMethods
)
{
tty
->
print_cr
(
"Creating overpasses..."
);
tty
->
print_cr
(
"Creating overpasses..."
);
...
@@ -893,7 +1018,6 @@ void DefaultMethods::generate_default_methods(
...
@@ -893,7 +1018,6 @@ void DefaultMethods::generate_default_methods(
#endif // ndef PRODUCT
#endif // ndef PRODUCT
}
}
/**
/**
* Generic analysis was used upon interface '_target' and found a unique
* Generic analysis was used upon interface '_target' and found a unique
* default method candidate with generic signature '_method_desc'. This
* default method candidate with generic signature '_method_desc'. This
...
@@ -912,17 +1036,85 @@ void DefaultMethods::generate_default_methods(
...
@@ -912,17 +1036,85 @@ void DefaultMethods::generate_default_methods(
* the selected method along that path.
* the selected method along that path.
*/
*/
class
ShadowChecker
:
public
HierarchyVisitor
<
ShadowChecker
>
{
class
ShadowChecker
:
public
HierarchyVisitor
<
ShadowChecker
>
{
private:
protected:
generic
::
DescriptorCache
*
_cache
;
Thread
*
THREAD
;
Thread
*
THREAD
;
InstanceKlass
*
_target
;
InstanceKlass
*
_target
;
Symbol
*
_method_name
;
Symbol
*
_method_name
;
InstanceKlass
*
_method_holder
;
InstanceKlass
*
_method_holder
;
generic
::
MethodDescriptor
*
_method_desc
;
bool
_found_shadow
;
bool
_found_shadow
;
public:
ShadowChecker
(
Thread
*
thread
,
Symbol
*
name
,
InstanceKlass
*
holder
,
InstanceKlass
*
target
)
:
THREAD
(
thread
),
_method_name
(
name
),
_method_holder
(
holder
),
_target
(
target
),
_found_shadow
(
false
)
{}
void
*
new_node_data
(
InstanceKlass
*
cls
)
{
return
NULL
;
}
void
free_node_data
(
void
*
data
)
{
return
;
}
bool
visit
()
{
InstanceKlass
*
ik
=
current_class
();
if
(
ik
==
_target
&&
current_depth
()
==
1
)
{
return
false
;
// This was the specified super -- no need to search it
}
if
(
ik
==
_method_holder
||
ik
==
_target
)
{
// We found a path that should be examined to see if it shadows _method
if
(
path_has_shadow
())
{
_found_shadow
=
true
;
cancel_iteration
();
}
return
false
;
// no need to continue up hierarchy
}
return
true
;
}
virtual
bool
path_has_shadow
()
=
0
;
bool
found_shadow
()
{
return
_found_shadow
;
}
};
// Used for Invokespecial.
// Invokespecial is allowed to invoke a concrete interface method
// and can be used to disambuiguate among qualified candidates,
// which are methods in immediate superinterfaces,
// but may not be used to invoke a candidate that would be shadowed
// from the perspective of the caller.
// Invokespecial is also used in the overpass generation today
// We re-run the shadowchecker because we can't distinguish this case,
// but it should return the same answer, since the overpass target
// is now the invokespecial caller.
class
ErasedShadowChecker
:
public
ShadowChecker
{
private:
bool
path_has_shadow
()
{
for
(
int
i
=
current_depth
()
-
1
;
i
>
0
;
--
i
)
{
InstanceKlass
*
ik
=
class_at_depth
(
i
);
if
(
ik
->
is_interface
())
{
int
end
;
int
start
=
ik
->
find_method_by_name
(
_method_name
,
&
end
);
if
(
start
!=
-
1
)
{
return
true
;
}
}
}
return
false
;
}
public:
ErasedShadowChecker
(
Thread
*
thread
,
Symbol
*
name
,
InstanceKlass
*
holder
,
InstanceKlass
*
target
)
:
ShadowChecker
(
thread
,
name
,
holder
,
target
)
{}
};
class
GenericShadowChecker
:
public
ShadowChecker
{
private:
generic
::
DescriptorCache
*
_cache
;
generic
::
MethodDescriptor
*
_method_desc
;
bool
path_has_shadow
()
{
bool
path_has_shadow
()
{
generic
::
Context
ctx
(
_cache
);
generic
::
Context
ctx
(
_cache
);
...
@@ -950,90 +1142,93 @@ class ShadowChecker : public HierarchyVisitor<ShadowChecker> {
...
@@ -950,90 +1142,93 @@ class ShadowChecker : public HierarchyVisitor<ShadowChecker> {
public:
public:
ShadowChecker
(
generic
::
DescriptorCache
*
cache
,
Thread
*
thread
,
Generic
ShadowChecker
(
generic
::
DescriptorCache
*
cache
,
Thread
*
thread
,
Symbol
*
name
,
InstanceKlass
*
holder
,
generic
::
MethodDescriptor
*
desc
,
Symbol
*
name
,
InstanceKlass
*
holder
,
generic
::
MethodDescriptor
*
desc
,
InstanceKlass
*
target
)
InstanceKlass
*
target
)
:
_cache
(
cache
),
THREAD
(
thread
),
_method_name
(
name
),
_method_holder
(
holder
),
:
ShadowChecker
(
thread
,
name
,
holder
,
target
)
{
_method_desc
(
desc
),
_target
(
target
),
_found_shadow
(
false
)
{}
_cache
=
cache
;
_method_desc
=
desc
;
}
};
void
*
new_node_data
(
InstanceKlass
*
cls
)
{
return
NULL
;
}
void
free_node_data
(
void
*
data
)
{
return
;
}
bool
visit
()
{
InstanceKlass
*
ik
=
current_class
();
if
(
ik
==
_target
&&
current_depth
()
==
1
)
{
return
false
;
// This was the specified super -- no need to search it
}
if
(
ik
==
_method_holder
||
ik
==
_target
)
{
// We found a path that should be examined to see if it shadows _method
if
(
path_has_shadow
())
{
_found_shadow
=
true
;
cancel_iteration
();
}
return
false
;
// no need to continue up hierarchy
}
return
true
;
}
bool
found_shadow
()
{
return
_found_shadow
;
}
// Find the unique qualified candidate from the perspective of the super_class
};
// which is the resolved_klass, which must be an immediate superinterface
// of klass
Method
*
find_erased_super_default
(
InstanceKlass
*
current_class
,
InstanceKlass
*
super_class
,
Symbol
*
method_name
,
Symbol
*
sig
,
TRAPS
)
{
// This is called during linktime when we find an invokespecial call that
FindMethodsByErasedSig
visitor
(
method_name
,
sig
);
// refers to a direct superinterface. It indicates that we should find the
visitor
.
run
(
super_class
);
// find candidates from resolved_klass
// default method in the hierarchy of that superinterface, and if that method
// would have been a candidate from the point of view of 'this' class, then we
// return that method.
Method
*
DefaultMethods
::
find_super_default
(
Klass
*
cls
,
Klass
*
super
,
Symbol
*
method_name
,
Symbol
*
sig
,
TRAPS
)
{
ResourceMark
rm
(
THREAD
);
MethodFamily
*
family
;
visitor
.
get_discovered_family
(
&
family
);
assert
(
cls
!=
NULL
&&
super
!=
NULL
,
"Need real classes"
);
if
(
family
!=
NULL
)
{
family
->
determine_target
(
current_class
,
CHECK_NULL
);
// get target from current_class
}
InstanceKlass
*
current_class
=
InstanceKlass
::
cast
(
cls
);
if
(
family
->
has_target
())
{
InstanceKlass
*
direction
=
InstanceKlass
::
cast
(
super
);
Method
*
target
=
family
->
get_selected_target
();
InstanceKlass
*
holder
=
InstanceKlass
::
cast
(
target
->
method_holder
());
// Keep entire hierarchy alive for the duration of the computation
// Verify that the identified method is valid from the context of
KeepAliveRegistrar
keepAlive
(
THREAD
);
// the current class, which is the caller class for invokespecial
KeepAliveVisitor
loadKeepAlive
(
&
keepAlive
);
// link resolution, i.e. ensure there it is not shadowed.
loadKeepAlive
.
run
(
current_class
);
// You can use invokespecial to disambiguate interface methods, but
// you can not use it to skip over an interface method that would shadow it.
ErasedShadowChecker
checker
(
THREAD
,
target
->
name
(),
holder
,
super_class
);
checker
.
run
(
current_class
);
if
(
checker
.
found_shadow
())
{
#ifndef PRODUCT
#ifndef PRODUCT
if
(
TraceDefaultMethods
)
{
if
(
TraceDefaultMethods
)
{
tty
->
print_cr
(
"Finding super default method %s.%s%s from %s"
,
tty
->
print_cr
(
" Only candidate found was shadowed."
);
direction
->
name
()
->
as_C_string
(),
method_name
->
as_C_string
(),
sig
->
as_C_string
(),
current_class
->
name
()
->
as_C_string
());
}
}
#endif // ndef PRODUCT
#endif // ndef PRODUCT
THROW_MSG_
(
vmSymbols
::
java_lang_AbstractMethodError
(),
if
(
!
direction
->
is_interface
())
{
"Accessible default method not found"
,
NULL
);
// We should not be here
}
else
{
return
NULL
;
#ifndef PRODUCT
if
(
TraceDefaultMethods
)
{
family
->
print_sig_on
(
tty
,
target
->
signature
(),
1
);
}
#endif // ndef PRODUCT
return
target
;
}
}
}
else
{
assert
(
family
->
throws_exception
(),
"must have target or throw"
);
THROW_MSG_
(
vmSymbols
::
java_lang_AbstractMethodError
(),
family
->
get_exception_message
()
->
as_C_string
(),
NULL
);
}
}
// super_class is assumed to be the direct super of current_class
Method
*
find_generic_super_default
(
InstanceKlass
*
current_class
,
InstanceKlass
*
super_class
,
Symbol
*
method_name
,
Symbol
*
sig
,
TRAPS
)
{
generic
::
DescriptorCache
cache
;
generic
::
DescriptorCache
cache
;
generic
::
Context
ctx
(
&
cache
);
generic
::
Context
ctx
(
&
cache
);
// Prime the initial generic context for current ->
direction
// Prime the initial generic context for current ->
super_class
ctx
.
apply_type_arguments
(
current_class
,
direction
,
CHECK_NULL
);
ctx
.
apply_type_arguments
(
current_class
,
super_class
,
CHECK_NULL
);
FindMethodsBy
Name
visitor
(
&
cache
,
method_name
,
&
ctx
,
CHECK_NULL
);
FindMethodsBy
GenericSig
visitor
(
&
cache
,
method_name
,
&
ctx
,
CHECK_NULL
);
visitor
.
run
(
direction
);
visitor
.
run
(
super_class
);
GrowableArray
<
MethodFamily
*>
families
;
GrowableArray
<
Generic
MethodFamily
*>
families
;
visitor
.
get_discovered_families
(
&
families
);
visitor
.
get_discovered_families
(
&
families
);
#ifndef PRODUCT
#ifndef PRODUCT
if
(
TraceDefaultMethods
)
{
if
(
TraceDefaultMethods
)
{
print_families
(
&
families
,
sig
);
print_
generic_
families
(
&
families
,
sig
);
}
}
#endif // ndef PRODUCT
#endif // ndef PRODUCT
MethodFamily
*
selected_family
=
NULL
;
Generic
MethodFamily
*
selected_family
=
NULL
;
for
(
int
i
=
0
;
i
<
families
.
length
();
++
i
)
{
for
(
int
i
=
0
;
i
<
families
.
length
();
++
i
)
{
MethodFamily
*
lm
=
families
.
at
(
i
);
Generic
MethodFamily
*
lm
=
families
.
at
(
i
);
if
(
lm
->
contains_signature
(
sig
))
{
if
(
lm
->
contains_signature
(
sig
))
{
lm
->
determine_target
(
current_class
,
CHECK_NULL
);
lm
->
determine_target
(
current_class
,
CHECK_NULL
);
selected_family
=
lm
;
selected_family
=
lm
;
...
@@ -1046,8 +1241,8 @@ Method* DefaultMethods::find_super_default(
...
@@ -1046,8 +1241,8 @@ Method* DefaultMethods::find_super_default(
// Verify that the identified method is valid from the context of
// Verify that the identified method is valid from the context of
// the current class
// the current class
ShadowChecker
checker
(
&
cache
,
THREAD
,
target
->
name
(),
Generic
ShadowChecker
checker
(
&
cache
,
THREAD
,
target
->
name
(),
holder
,
selected_family
->
descriptor
(),
direction
);
holder
,
selected_family
->
descriptor
(),
super_class
);
checker
.
run
(
current_class
);
checker
.
run
(
current_class
);
if
(
checker
.
found_shadow
())
{
if
(
checker
.
found_shadow
())
{
...
@@ -1059,22 +1254,80 @@ Method* DefaultMethods::find_super_default(
...
@@ -1059,22 +1254,80 @@ Method* DefaultMethods::find_super_default(
THROW_MSG_
(
vmSymbols
::
java_lang_AbstractMethodError
(),
THROW_MSG_
(
vmSymbols
::
java_lang_AbstractMethodError
(),
"Accessible default method not found"
,
NULL
);
"Accessible default method not found"
,
NULL
);
}
else
{
}
else
{
return
target
;
}
}
else
{
assert
(
selected_family
->
throws_exception
(),
"must have target or throw"
);
THROW_MSG_
(
vmSymbols
::
java_lang_AbstractMethodError
(),
selected_family
->
get_exception_message
()
->
as_C_string
(),
NULL
);
}
}
// This is called during linktime when we find an invokespecial call that
// refers to a direct superinterface. It indicates that we should find the
// default method in the hierarchy of that superinterface, and if that method
// would have been a candidate from the point of view of 'this' class, then we
// return that method.
// This logic assumes that the super is a direct superclass of the caller
Method
*
DefaultMethods
::
find_super_default
(
Klass
*
cls
,
Klass
*
super
,
Symbol
*
method_name
,
Symbol
*
sig
,
TRAPS
)
{
ResourceMark
rm
(
THREAD
);
assert
(
cls
!=
NULL
&&
super
!=
NULL
,
"Need real classes"
);
InstanceKlass
*
current_class
=
InstanceKlass
::
cast
(
cls
);
InstanceKlass
*
super_class
=
InstanceKlass
::
cast
(
super
);
// Keep entire hierarchy alive for the duration of the computation
KeepAliveRegistrar
keepAlive
(
THREAD
);
KeepAliveVisitor
loadKeepAlive
(
&
keepAlive
);
loadKeepAlive
.
run
(
current_class
);
// get hierarchy from current class
#ifndef PRODUCT
if
(
TraceDefaultMethods
)
{
tty
->
print_cr
(
"Finding super default method %s.%s%s from %s"
,
super_class
->
name
()
->
as_C_string
(),
method_name
->
as_C_string
(),
sig
->
as_C_string
(),
current_class
->
name
()
->
as_C_string
());
}
#endif // ndef PRODUCT
assert
(
super_class
->
is_interface
(),
"only call for default methods"
);
Method
*
target
=
NULL
;
if
(
ParseGenericDefaults
)
{
target
=
find_generic_super_default
(
current_class
,
super_class
,
method_name
,
sig
,
CHECK_NULL
);
}
else
{
target
=
find_erased_super_default
(
current_class
,
super_class
,
method_name
,
sig
,
CHECK_NULL
);
}
#ifndef PRODUCT
#ifndef PRODUCT
if
(
target
!=
NULL
)
{
if
(
TraceDefaultMethods
)
{
if
(
TraceDefaultMethods
)
{
tty
->
print
(
" Returning "
);
tty
->
print
(
" Returning "
);
print_method
(
tty
,
target
,
true
);
print_method
(
tty
,
target
,
true
);
tty
->
print_cr
(
""
);
tty
->
print_cr
(
""
);
}
}
}
#endif // ndef PRODUCT
#endif // ndef PRODUCT
return
target
;
return
target
;
}
#ifndef PRODUCT
// Return true is broad type is a covariant return of narrow type
static
bool
covariant_return_type
(
BasicType
narrow
,
BasicType
broad
)
{
if
(
narrow
==
broad
)
{
return
true
;
}
}
}
else
{
if
(
broad
==
T_OBJECT
)
{
assert
(
selected_family
->
throws_exception
(),
"must have target or throw"
);
return
true
;
THROW_MSG_
(
vmSymbols
::
java_lang_AbstractMethodError
(),
selected_family
->
get_exception_message
()
->
as_C_string
(),
NULL
);
}
}
return
false
;
}
}
#endif // ndef PRODUCT
static
int
assemble_redirect
(
static
int
assemble_redirect
(
BytecodeConstantPool
*
cp
,
BytecodeBuffer
*
buffer
,
BytecodeConstantPool
*
cp
,
BytecodeBuffer
*
buffer
,
...
@@ -1103,7 +1356,7 @@ static int assemble_redirect(
...
@@ -1103,7 +1356,7 @@ static int assemble_redirect(
out
.
next
();
out
.
next
();
}
}
assert
(
out
.
at_return_type
(),
"Parameter counts do not match"
);
assert
(
out
.
at_return_type
(),
"Parameter counts do not match"
);
assert
(
in
.
type
()
==
out
.
type
(
),
"Return types are not compatible"
);
assert
(
covariant_return_type
(
out
.
type
(),
in
.
type
()
),
"Return types are not compatible"
);
if
(
parameter_count
==
1
&&
(
in
.
type
()
==
T_LONG
||
in
.
type
()
==
T_DOUBLE
))
{
if
(
parameter_count
==
1
&&
(
in
.
type
()
==
T_LONG
||
in
.
type
()
==
T_DOUBLE
))
{
++
parameter_count
;
// need room for return value
++
parameter_count
;
// need room for return value
...
@@ -1144,10 +1397,15 @@ static Method* new_method(
...
@@ -1144,10 +1397,15 @@ static Method* new_method(
Symbol
*
sig
,
AccessFlags
flags
,
int
max_stack
,
int
params
,
Symbol
*
sig
,
AccessFlags
flags
,
int
max_stack
,
int
params
,
ConstMethod
::
MethodType
mt
,
TRAPS
)
{
ConstMethod
::
MethodType
mt
,
TRAPS
)
{
address
code_start
=
static_cast
<
address
>
(
bytecodes
->
adr_at
(
0
))
;
address
code_start
=
0
;
int
code_length
=
bytecodes
->
length
()
;
int
code_length
=
0
;
InlineTableSizes
sizes
;
InlineTableSizes
sizes
;
if
(
bytecodes
!=
NULL
&&
bytecodes
->
length
()
>
0
)
{
code_start
=
static_cast
<
address
>
(
bytecodes
->
adr_at
(
0
));
code_length
=
bytecodes
->
length
();
}
Method
*
m
=
Method
::
allocate
(
cp
->
pool_holder
()
->
class_loader_data
(),
Method
*
m
=
Method
::
allocate
(
cp
->
pool_holder
()
->
class_loader_data
(),
code_length
,
flags
,
&
sizes
,
code_length
,
flags
,
&
sizes
,
mt
,
CHECK_NULL
);
mt
,
CHECK_NULL
);
...
...
src/share/vm/runtime/globals.hpp
浏览文件 @
567a6555
...
@@ -3679,6 +3679,9 @@ class CommandLineFlags {
...
@@ -3679,6 +3679,9 @@ class CommandLineFlags {
develop(bool, VerifyGenericSignatures, false, \
develop(bool, VerifyGenericSignatures, false, \
"Abort VM on erroneous or inconsistent generic signatures") \
"Abort VM on erroneous or inconsistent generic signatures") \
\
\
product(bool, ParseGenericDefaults, false, \
"Parse generic signatures for default method handling") \
\
product(bool, UseVMInterruptibleIO, false, \
product(bool, UseVMInterruptibleIO, false, \
"(Unstable, Solaris-specific) Thread interrupt before or with " \
"(Unstable, Solaris-specific) Thread interrupt before or with " \
"EINTR for I/O operations results in OS_INTRPT. The default value"\
"EINTR for I/O operations results in OS_INTRPT. The default value"\
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录