Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
2182157d
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看板
提交
2182157d
编写于
8月 26, 2013
作者:
A
acorn
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8012294: remove generic handling for default methods
Reviewed-by: kamg, coleenp
上级
13b030b0
变更
5
显示空白变更内容
内联
并排
Showing
5 changed file
with
10 addition
and
2145 deletion
+10
-2145
src/share/vm/classfile/classFileParser.cpp
src/share/vm/classfile/classFileParser.cpp
+0
-36
src/share/vm/classfile/defaultMethods.cpp
src/share/vm/classfile/defaultMethods.cpp
+10
-357
src/share/vm/classfile/genericSignatures.cpp
src/share/vm/classfile/genericSignatures.cpp
+0
-1279
src/share/vm/classfile/genericSignatures.hpp
src/share/vm/classfile/genericSignatures.hpp
+0
-467
src/share/vm/runtime/globals.hpp
src/share/vm/runtime/globals.hpp
+0
-6
未找到文件。
src/share/vm/classfile/classFileParser.cpp
浏览文件 @
2182157d
...
...
@@ -28,7 +28,6 @@
#include "classfile/classLoaderData.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/defaultMethods.hpp"
#include "classfile/genericSignatures.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
...
...
@@ -3039,35 +3038,6 @@ AnnotationArray* ClassFileParser::assemble_annotations(u1* runtime_visible_annot
return
annotations
;
}
#ifdef ASSERT
static
void
parseAndPrintGenericSignatures
(
instanceKlassHandle
this_klass
,
TRAPS
)
{
assert
(
ParseAllGenericSignatures
==
true
,
"Shouldn't call otherwise"
);
ResourceMark
rm
;
if
(
this_klass
->
generic_signature
()
!=
NULL
)
{
using
namespace
generic
;
ClassDescriptor
*
spec
=
ClassDescriptor
::
parse_generic_signature
(
this_klass
(),
CHECK
);
tty
->
print_cr
(
"Parsing %s"
,
this_klass
->
generic_signature
()
->
as_C_string
());
spec
->
print_on
(
tty
);
for
(
int
i
=
0
;
i
<
this_klass
->
methods
()
->
length
();
++
i
)
{
Method
*
m
=
this_klass
->
methods
()
->
at
(
i
);
MethodDescriptor
*
method_spec
=
MethodDescriptor
::
parse_generic_signature
(
m
,
spec
);
Symbol
*
sig
=
m
->
generic_signature
();
if
(
sig
==
NULL
)
{
sig
=
m
->
signature
();
}
tty
->
print_cr
(
"Parsing %s"
,
sig
->
as_C_string
());
method_spec
->
print_on
(
tty
);
}
}
}
#endif // def ASSERT
instanceKlassHandle
ClassFileParser
::
parse_super_class
(
int
super_class_index
,
TRAPS
)
{
instanceKlassHandle
super_klass
;
...
...
@@ -4060,12 +4030,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
java_lang_Class
::
create_mirror
(
this_klass
,
protection_domain
,
CHECK_
(
nullHandle
));
#ifdef ASSERT
if
(
ParseAllGenericSignatures
)
{
parseAndPrintGenericSignatures
(
this_klass
,
CHECK_
(
nullHandle
));
}
#endif
// Generate any default methods - default methods are interface methods
// that have a default implementation. This is new with Lambda project.
if
(
has_default_methods
&&
!
access_flags
.
is_interface
()
&&
...
...
src/share/vm/classfile/defaultMethods.cpp
浏览文件 @
2182157d
...
...
@@ -25,7 +25,6 @@
#include "precompiled.hpp"
#include "classfile/bytecodeAssembler.hpp"
#include "classfile/defaultMethods.hpp"
#include "classfile/genericSignatures.hpp"
#include "classfile/symbolTable.hpp"
#include "memory/allocation.hpp"
#include "memory/metadataFactory.hpp"
...
...
@@ -75,14 +74,6 @@ class PseudoScope : public ResourceObj {
}
};
class
ContextMark
:
public
PseudoScopeMark
{
private:
generic
::
Context
::
Mark
_mark
;
public:
ContextMark
(
const
generic
::
Context
::
Mark
&
cm
)
:
_mark
(
cm
)
{}
virtual
void
destroy
()
{
_mark
.
destroy
();
}
};
#ifndef PRODUCT
static
void
print_slot
(
outputStream
*
str
,
Symbol
*
name
,
Symbol
*
signature
)
{
ResourceMark
rm
;
...
...
@@ -503,38 +494,6 @@ Symbol* MethodFamily::generate_conflicts_message(GrowableArray<Method*>* methods
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
;
...
...
@@ -571,26 +530,6 @@ class StatefulMethodFamily : public ResourceObj {
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
{
private:
StatefulMethodFamily
*
_method
;
...
...
@@ -616,39 +555,6 @@ StateRestorer* StatefulMethodFamily::record_method_and_dq_further(Method* mo) {
return
mark
;
}
class
StatefulGenericMethodFamilies
:
public
ResourceObj
{
private:
GrowableArray
<
StatefulGenericMethodFamily
*>
_methods
;
public:
StatefulGenericMethodFamily
*
find_matching
(
generic
::
MethodDescriptor
*
md
,
generic
::
Context
*
ctx
)
{
for
(
int
i
=
0
;
i
<
_methods
.
length
();
++
i
)
{
StatefulGenericMethodFamily
*
existing
=
_methods
.
at
(
i
);
if
(
existing
->
descriptor_matches
(
md
,
ctx
))
{
return
existing
;
}
}
return
NULL
;
}
StatefulGenericMethodFamily
*
find_matching_or_create
(
generic
::
MethodDescriptor
*
md
,
generic
::
Context
*
ctx
)
{
StatefulGenericMethodFamily
*
method
=
find_matching
(
md
,
ctx
);
if
(
method
==
NULL
)
{
method
=
new
StatefulGenericMethodFamily
(
md
,
ctx
);
_methods
.
append
(
method
);
}
return
method
;
}
void
extract_families_into
(
GrowableArray
<
GenericMethodFamily
*>*
array
)
{
for
(
int
i
=
0
;
i
<
_methods
.
length
();
++
i
)
{
array
->
append
(
_methods
.
at
(
i
)
->
get_method_family
());
}
}
};
// Represents a location corresponding to a vtable slot for methods that
// neither the class nor any of it's ancestors provide an implementaion.
// Default methods may be present to fill this slot.
...
...
@@ -779,146 +685,11 @@ class FindMethodsByErasedSig : public HierarchyVisitor<FindMethodsByErasedSig> {
};
// 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
// which is populated with a set of methods that implement the same
// language-level signature.
class
FindMethodsByGenericSig
:
public
HierarchyVisitor
<
FindMethodsByGenericSig
>
{
private:
// Context data
Thread
*
THREAD
;
generic
::
DescriptorCache
*
_cache
;
Symbol
*
_method_name
;
generic
::
Context
*
_ctx
;
StatefulGenericMethodFamilies
_families
;
public:
FindMethodsByGenericSig
(
generic
::
DescriptorCache
*
cache
,
Symbol
*
name
,
generic
::
Context
*
ctx
,
Thread
*
thread
)
:
_cache
(
cache
),
_method_name
(
name
),
_ctx
(
ctx
),
THREAD
(
thread
)
{}
void
get_discovered_families
(
GrowableArray
<
GenericMethodFamily
*>*
methods
)
{
_families
.
extract_families_into
(
methods
);
}
void
*
new_node_data
(
InstanceKlass
*
cls
)
{
return
new
PseudoScope
();
}
void
free_node_data
(
void
*
node_data
)
{
PseudoScope
::
cast
(
node_data
)
->
destroy
();
}
bool
visit
()
{
PseudoScope
*
scope
=
PseudoScope
::
cast
(
current_data
());
InstanceKlass
*
klass
=
current_class
();
InstanceKlass
*
sub
=
current_depth
()
>
0
?
class_at_depth
(
1
)
:
NULL
;
ContextMark
*
cm
=
new
ContextMark
(
_ctx
->
mark
());
scope
->
add_mark
(
cm
);
// will restore context when scope is freed
_ctx
->
apply_type_arguments
(
sub
,
klass
,
THREAD
);
int
start
,
end
=
0
;
start
=
klass
->
find_method_by_name
(
_method_name
,
&
end
);
if
(
start
!=
-
1
)
{
for
(
int
i
=
start
;
i
<
end
;
++
i
)
{
Method
*
m
=
klass
->
methods
()
->
at
(
i
);
// This gets the method's parameter list with its generic type
// parameters resolved
generic
::
MethodDescriptor
*
md
=
_cache
->
descriptor_for
(
m
,
THREAD
);
// Find all methods on this hierarchy that match this method
// (name, signature). This class collects other families of this
// method name.
StatefulGenericMethodFamily
*
family
=
_families
.
find_matching_or_create
(
md
,
_ctx
);
if
(
klass
->
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
;
}
};
#ifndef PRODUCT
static
void
print_generic_families
(
GrowableArray
<
GenericMethodFamily
*>*
methods
,
Symbol
*
match
)
{
streamIndentor
si
(
tty
,
4
);
if
(
methods
->
length
()
==
0
)
{
tty
->
indent
();
tty
->
print_cr
(
"No Logical Method found"
);
}
for
(
int
i
=
0
;
i
<
methods
->
length
();
++
i
)
{
tty
->
indent
();
GenericMethodFamily
*
lm
=
methods
->
at
(
i
);
if
(
lm
->
contains_signature
(
match
))
{
tty
->
print_cr
(
"<Matching>"
);
}
else
{
tty
->
print_cr
(
"<Non-Matching>"
);
}
lm
->
print_sig_on
(
tty
,
lm
->
get_generic_sig
(),
1
);
}
}
#endif // ndef PRODUCT
static
void
create_overpasses
(
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
)
{
...
...
@@ -943,21 +714,14 @@ static void merge_in_new_methods(InstanceKlass* klass,
//
// First if finds any name/signature slots that need any implementation (either
// because they are miranda or a superclass's implementation is an overpass
// itself). For each slot, iterate over the hierarchy, using generic signature
// information to partition any methods that match the name into method families
// where each family contains methods whose signatures are equivalent at the
// language level (i.e., their reified parameters match and return values are
// covariant). Check those sets to see if they contain a signature that matches
// the slot we're looking at (if we're lucky, there might be other empty slots
// that we can fill using the same analysis).
// itself). For each slot, iterate over the hierarchy, to see if they contain a
// signature that matches the slot we are looking at.
//
// For each slot filled, we generate an overpass method that either calls the
// unique default method candidate using invokespecial, or throws an exception
// (in the case of no default method candidates, or more than one valid
// candidate). These methods are then added to the class's method list. If
// the method set we're using contains methods (qualified or not) with a
// different runtime signature than the method we're creating, then we have to
// create bridges with those signatures too.
// candidate). These methods are then added to the class's method list.
// The JVM does not create bridges nor handle generic signatures here.
void
DefaultMethods
::
generate_default_methods
(
InstanceKlass
*
klass
,
GrowableArray
<
Method
*>*
mirandas
,
TRAPS
)
{
...
...
@@ -997,12 +761,8 @@ void DefaultMethods::generate_default_methods(
}
#endif // ndef PRODUCT
if
(
ParseGenericDefaults
)
{
generate_generic_defaults
(
klass
,
empty_slots
,
slot
,
i
,
CHECK
);
}
else
{
generate_erased_defaults
(
klass
,
empty_slots
,
slot
,
CHECK
);
}
}
#ifndef PRODUCT
if
(
TraceDefaultMethods
)
{
tty
->
print_cr
(
"Creating overpasses..."
);
...
...
@@ -1019,13 +779,13 @@ void DefaultMethods::generate_default_methods(
}
/**
*
Generic analysis was used upon interface '_target' and found a unique
*
default method candidate with generic signature '_method_desc'.
This
*
Interface inheritance rules were used to find a unique default method
*
candidate for the resolved class.
This
* method is only viable if it would also be in the set of default method
* candidates if we ran a full analysis on the current class.
*
* The only reason that the method would not be in the set of candidates for
* the current class is if that there's another
covariantly
matching method
* the current class is if that there's another matching method
* which is "more specific" than the found method -- i.e., one could find a
* path in the interface hierarchy in which the matching method appears
* before we get to '_target'.
...
...
@@ -1110,48 +870,6 @@ class ErasedShadowChecker : public ShadowChecker {
:
ShadowChecker
(
thread
,
name
,
holder
,
target
)
{}
};
class
GenericShadowChecker
:
public
ShadowChecker
{
private:
generic
::
DescriptorCache
*
_cache
;
generic
::
MethodDescriptor
*
_method_desc
;
bool
path_has_shadow
()
{
generic
::
Context
ctx
(
_cache
);
for
(
int
i
=
current_depth
()
-
1
;
i
>
0
;
--
i
)
{
InstanceKlass
*
ik
=
class_at_depth
(
i
);
InstanceKlass
*
sub
=
class_at_depth
(
i
+
1
);
ctx
.
apply_type_arguments
(
sub
,
ik
,
THREAD
);
if
(
ik
->
is_interface
())
{
int
end
;
int
start
=
ik
->
find_method_by_name
(
_method_name
,
&
end
);
if
(
start
!=
-
1
)
{
for
(
int
j
=
start
;
j
<
end
;
++
j
)
{
Method
*
mo
=
ik
->
methods
()
->
at
(
j
);
generic
::
MethodDescriptor
*
md
=
_cache
->
descriptor_for
(
mo
,
THREAD
);
if
(
_method_desc
->
covariant_match
(
md
,
&
ctx
))
{
return
true
;
}
}
}
}
}
return
false
;
}
public:
GenericShadowChecker
(
generic
::
DescriptorCache
*
cache
,
Thread
*
thread
,
Symbol
*
name
,
InstanceKlass
*
holder
,
generic
::
MethodDescriptor
*
desc
,
InstanceKlass
*
target
)
:
ShadowChecker
(
thread
,
name
,
holder
,
target
)
{
_cache
=
cache
;
_method_desc
=
desc
;
}
};
// Find the unique qualified candidate from the perspective of the super_class
// which is the resolved_klass, which must be an immediate superinterface
...
...
@@ -1203,66 +921,6 @@ Method* find_erased_super_default(InstanceKlass* current_class, InstanceKlass* s
}
}
// 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
::
Context
ctx
(
&
cache
);
// Prime the initial generic context for current -> super_class
ctx
.
apply_type_arguments
(
current_class
,
super_class
,
CHECK_NULL
);
FindMethodsByGenericSig
visitor
(
&
cache
,
method_name
,
&
ctx
,
CHECK_NULL
);
visitor
.
run
(
super_class
);
GrowableArray
<
GenericMethodFamily
*>
families
;
visitor
.
get_discovered_families
(
&
families
);
#ifndef PRODUCT
if
(
TraceDefaultMethods
)
{
print_generic_families
(
&
families
,
sig
);
}
#endif // ndef PRODUCT
GenericMethodFamily
*
selected_family
=
NULL
;
for
(
int
i
=
0
;
i
<
families
.
length
();
++
i
)
{
GenericMethodFamily
*
lm
=
families
.
at
(
i
);
if
(
lm
->
contains_signature
(
sig
))
{
lm
->
determine_target
(
current_class
,
CHECK_NULL
);
selected_family
=
lm
;
}
}
if
(
selected_family
->
has_target
())
{
Method
*
target
=
selected_family
->
get_selected_target
();
InstanceKlass
*
holder
=
InstanceKlass
::
cast
(
target
->
method_holder
());
// Verify that the identified method is valid from the context of
// the current class
GenericShadowChecker
checker
(
&
cache
,
THREAD
,
target
->
name
(),
holder
,
selected_family
->
descriptor
(),
super_class
);
checker
.
run
(
current_class
);
if
(
checker
.
found_shadow
())
{
#ifndef PRODUCT
if
(
TraceDefaultMethods
)
{
tty
->
print_cr
(
" Only candidate found was shadowed."
);
}
#endif // ndef PRODUCT
THROW_MSG_
(
vmSymbols
::
java_lang_AbstractMethodError
(),
"Accessible default method not found"
,
NULL
);
}
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
...
...
@@ -1296,13 +954,8 @@ Method* DefaultMethods::find_super_default(
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
if
(
target
!=
NULL
)
{
...
...
src/share/vm/classfile/genericSignatures.cpp
已删除
100644 → 0
浏览文件 @
13b030b0
/*
* Copyright (c) 2012, 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.
*
*/
#include "precompiled.hpp"
#include "classfile/genericSignatures.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "memory/resourceArea.hpp"
namespace
generic
{
// Helper class for parsing the generic signature Symbol in klass and methods
class
DescriptorStream
:
public
ResourceObj
{
private:
Symbol
*
_symbol
;
int
_offset
;
int
_mark
;
const
char
*
_parse_error
;
void
set_parse_error
(
const
char
*
error
)
{
assert
(
error
!=
NULL
,
"Can't set NULL error string"
);
_parse_error
=
error
;
}
public:
DescriptorStream
(
Symbol
*
sym
)
:
_symbol
(
sym
),
_offset
(
0
),
_mark
(
-
1
),
_parse_error
(
NULL
)
{}
const
char
*
parse_error
()
const
{
return
_parse_error
;
}
bool
at_end
()
{
return
_offset
>=
_symbol
->
utf8_length
();
}
char
peek
()
{
if
(
at_end
())
{
set_parse_error
(
"Peeking past end of signature"
);
return
'\0'
;
}
else
{
return
_symbol
->
byte_at
(
_offset
);
}
}
char
read
()
{
if
(
at_end
())
{
set_parse_error
(
"Reading past end of signature"
);
return
'\0'
;
}
else
{
return
_symbol
->
byte_at
(
_offset
++
);
}
}
void
read
(
char
expected
)
{
char
c
=
read
();
assert_char
(
c
,
expected
,
0
);
}
void
assert_char
(
char
c
,
char
expected
,
int
pos
=
-
1
)
{
if
(
c
!=
expected
)
{
const
char
*
fmt
=
"Parse error at %d: expected %c but got %c"
;
size_t
len
=
strlen
(
fmt
)
+
5
;
char
*
buffer
=
NEW_RESOURCE_ARRAY
(
char
,
len
);
jio_snprintf
(
buffer
,
len
,
fmt
,
_offset
+
pos
,
expected
,
c
);
set_parse_error
(
buffer
);
}
}
void
push
(
char
c
)
{
assert
(
c
==
_symbol
->
byte_at
(
_offset
-
1
),
"Pushing back wrong value"
);
--
_offset
;
}
void
expect_end
()
{
if
(
!
at_end
())
{
set_parse_error
(
"Unexpected data trailing signature"
);
}
}
bool
has_mark
()
{
return
_mark
!=
-
1
;
}
void
set_mark
()
{
_mark
=
_offset
;
}
Identifier
*
identifier_from_mark
()
{
assert
(
has_mark
(),
"Mark should be set"
);
if
(
!
has_mark
())
{
set_parse_error
(
"Expected mark to be set"
);
return
NULL
;
}
else
{
Identifier
*
id
=
new
Identifier
(
_symbol
,
_mark
,
_offset
-
1
);
_mark
=
-
1
;
return
id
;
}
}
};
#define CHECK_FOR_PARSE_ERROR() \
if (STREAM->parse_error() != NULL) { \
if (VerifyGenericSignatures) { \
fatal(STREAM->parse_error()); \
} \
return NULL; \
} (void)0
#define READ() STREAM->read(); CHECK_FOR_PARSE_ERROR()
#define PEEK() STREAM->peek(); CHECK_FOR_PARSE_ERROR()
#define PUSH(c) STREAM->push(c)
#define EXPECT(c) STREAM->read(c); CHECK_FOR_PARSE_ERROR()
#define EXPECTED(c, ch) STREAM->assert_char(c, ch); CHECK_FOR_PARSE_ERROR()
#define EXPECT_END() STREAM->expect_end(); CHECK_FOR_PARSE_ERROR()
#define CHECK_STREAM STREAM); CHECK_FOR_PARSE_ERROR(); ((void)0
#ifndef PRODUCT
void
Identifier
::
print_on
(
outputStream
*
str
)
const
{
for
(
int
i
=
_begin
;
i
<
_end
;
++
i
)
{
str
->
print
(
"%c"
,
(
char
)
_sym
->
byte_at
(
i
));
}
}
#endif // ndef PRODUCT
bool
Identifier
::
equals
(
Identifier
*
other
)
{
if
(
_sym
==
other
->
_sym
&&
_begin
==
other
->
_begin
&&
_end
==
other
->
_end
)
{
return
true
;
}
else
if
(
_end
-
_begin
!=
other
->
_end
-
other
->
_begin
)
{
return
false
;
}
else
{
size_t
len
=
_end
-
_begin
;
char
*
addr
=
((
char
*
)
_sym
->
bytes
())
+
_begin
;
char
*
oaddr
=
((
char
*
)
other
->
_sym
->
bytes
())
+
other
->
_begin
;
return
strncmp
(
addr
,
oaddr
,
len
)
==
0
;
}
}
bool
Identifier
::
equals
(
Symbol
*
sym
)
{
Identifier
id
(
sym
,
0
,
sym
->
utf8_length
());
return
equals
(
&
id
);
}
/**
* A formal type parameter may be found in the the enclosing class, but it could
* also come from an enclosing method or outer class, in the case of inner-outer
* classes or anonymous classes. For example:
*
* class Outer<T,V> {
* class Inner<W> {
* void m(T t, V v, W w);
* }
* }
*
* In this case, the type variables in m()'s signature are not all found in the
* immediate enclosing class (Inner). class Inner has only type parameter W,
* but it's outer_class field will reference Outer's descriptor which contains
* T & V (no outer_method in this case).
*
* If you have an anonymous class, it has both an enclosing method *and* an
* enclosing class where type parameters can be declared:
*
* class MOuter<T> {
* <V> void bar(V v) {
* Runnable r = new Runnable() {
* public void run() {}
* public void foo(T t, V v) { ... }
* };
* }
* }
*
* In this case, foo will be a member of some class, Runnable$1, which has no
* formal parameters itself, but has an outer_method (bar()) which provides
* type parameter V, and an outer class MOuter with type parameter T.
*
* It is also possible that the outer class is itself an inner class to some
* other class (or an anonymous class with an enclosing method), so we need to
* follow the outer_class/outer_method chain to it's end when looking for a
* type parameter.
*/
TypeParameter
*
Descriptor
::
find_type_parameter
(
Identifier
*
id
,
int
*
depth
)
{
int
current_depth
=
0
;
MethodDescriptor
*
outer_method
=
as_method_signature
();
ClassDescriptor
*
outer_class
=
as_class_signature
();
if
(
outer_class
==
NULL
)
{
// 'this' is a method signature; use the holder
outer_class
=
outer_method
->
outer_class
();
}
while
(
outer_method
!=
NULL
||
outer_class
!=
NULL
)
{
if
(
outer_method
!=
NULL
)
{
for
(
int
i
=
0
;
i
<
outer_method
->
type_parameters
().
length
();
++
i
)
{
TypeParameter
*
p
=
outer_method
->
type_parameters
().
at
(
i
);
if
(
p
->
identifier
()
->
equals
(
id
))
{
*
depth
=
-
1
;
// indicates this this is a method parameter
return
p
;
}
}
}
if
(
outer_class
!=
NULL
)
{
for
(
int
i
=
0
;
i
<
outer_class
->
type_parameters
().
length
();
++
i
)
{
TypeParameter
*
p
=
outer_class
->
type_parameters
().
at
(
i
);
if
(
p
->
identifier
()
->
equals
(
id
))
{
*
depth
=
current_depth
;
return
p
;
}
}
outer_method
=
outer_class
->
outer_method
();
outer_class
=
outer_class
->
outer_class
();
++
current_depth
;
}
}
if
(
VerifyGenericSignatures
)
{
fatal
(
"Could not resolve identifier"
);
}
return
NULL
;
}
ClassDescriptor
*
ClassDescriptor
::
parse_generic_signature
(
Klass
*
klass
,
TRAPS
)
{
return
parse_generic_signature
(
klass
,
NULL
,
CHECK_NULL
);
}
ClassDescriptor
*
ClassDescriptor
::
parse_generic_signature
(
Klass
*
klass
,
Symbol
*
original_name
,
TRAPS
)
{
InstanceKlass
*
ik
=
InstanceKlass
::
cast
(
klass
);
Symbol
*
sym
=
ik
->
generic_signature
();
ClassDescriptor
*
spec
;
if
(
sym
==
NULL
||
(
spec
=
ClassDescriptor
::
parse_generic_signature
(
sym
))
==
NULL
)
{
spec
=
ClassDescriptor
::
placeholder
(
ik
);
}
u2
outer_index
=
get_outer_class_index
(
ik
,
CHECK_NULL
);
if
(
outer_index
!=
0
)
{
if
(
original_name
==
NULL
)
{
original_name
=
ik
->
name
();
}
Handle
class_loader
=
Handle
(
THREAD
,
ik
->
class_loader
());
Handle
protection_domain
=
Handle
(
THREAD
,
ik
->
protection_domain
());
Symbol
*
outer_name
=
ik
->
constants
()
->
klass_name_at
(
outer_index
);
Klass
*
outer
=
SystemDictionary
::
find
(
outer_name
,
class_loader
,
protection_domain
,
CHECK_NULL
);
if
(
outer
==
NULL
&&
!
THREAD
->
is_Compiler_thread
())
{
if
(
outer_name
==
ik
->
super
()
->
name
())
{
outer
=
SystemDictionary
::
resolve_super_or_fail
(
original_name
,
outer_name
,
class_loader
,
protection_domain
,
false
,
CHECK_NULL
);
}
else
{
outer
=
SystemDictionary
::
resolve_or_fail
(
outer_name
,
class_loader
,
protection_domain
,
false
,
CHECK_NULL
);
}
}
InstanceKlass
*
outer_ik
;
ClassDescriptor
*
outer_spec
=
NULL
;
if
(
outer
==
NULL
)
{
outer_spec
=
ClassDescriptor
::
placeholder
(
ik
);
assert
(
false
,
"Outer class not loaded and not loadable from here"
);
}
else
{
outer_ik
=
InstanceKlass
::
cast
(
outer
);
outer_spec
=
parse_generic_signature
(
outer
,
original_name
,
CHECK_NULL
);
}
spec
->
set_outer_class
(
outer_spec
);
u2
encl_method_idx
=
ik
->
enclosing_method_method_index
();
if
(
encl_method_idx
!=
0
&&
outer_ik
!=
NULL
)
{
ConstantPool
*
cp
=
ik
->
constants
();
u2
name_index
=
cp
->
name_ref_index_at
(
encl_method_idx
);
u2
sig_index
=
cp
->
signature_ref_index_at
(
encl_method_idx
);
Symbol
*
name
=
cp
->
symbol_at
(
name_index
);
Symbol
*
sig
=
cp
->
symbol_at
(
sig_index
);
Method
*
m
=
outer_ik
->
find_method
(
name
,
sig
);
if
(
m
!=
NULL
)
{
Symbol
*
gsig
=
m
->
generic_signature
();
if
(
gsig
!=
NULL
)
{
MethodDescriptor
*
gms
=
MethodDescriptor
::
parse_generic_signature
(
gsig
,
outer_spec
);
spec
->
set_outer_method
(
gms
);
}
}
else
if
(
VerifyGenericSignatures
)
{
ResourceMark
rm
;
stringStream
ss
;
ss
.
print
(
"Could not find method %s %s in class %s"
,
name
->
as_C_string
(),
sig
->
as_C_string
(),
outer_name
->
as_C_string
());
fatal
(
ss
.
as_string
());
}
}
}
spec
->
bind_variables_to_parameters
();
return
spec
;
}
ClassDescriptor
*
ClassDescriptor
::
placeholder
(
InstanceKlass
*
klass
)
{
GrowableArray
<
TypeParameter
*>
formals
;
GrowableArray
<
ClassType
*>
interfaces
;
ClassType
*
super_type
=
NULL
;
Klass
*
super_klass
=
klass
->
super
();
if
(
super_klass
!=
NULL
)
{
InstanceKlass
*
super
=
InstanceKlass
::
cast
(
super_klass
);
super_type
=
ClassType
::
from_symbol
(
super
->
name
());
}
for
(
int
i
=
0
;
i
<
klass
->
local_interfaces
()
->
length
();
++
i
)
{
InstanceKlass
*
iface
=
InstanceKlass
::
cast
(
klass
->
local_interfaces
()
->
at
(
i
));
interfaces
.
append
(
ClassType
::
from_symbol
(
iface
->
name
()));
}
return
new
ClassDescriptor
(
formals
,
super_type
,
interfaces
);
}
ClassDescriptor
*
ClassDescriptor
::
parse_generic_signature
(
Symbol
*
sym
)
{
DescriptorStream
ds
(
sym
);
DescriptorStream
*
STREAM
=
&
ds
;
GrowableArray
<
TypeParameter
*>
parameters
(
8
);
char
c
=
READ
();
if
(
c
==
'<'
)
{
c
=
READ
();
while
(
c
!=
'>'
)
{
PUSH
(
c
);
TypeParameter
*
ftp
=
TypeParameter
::
parse_generic_signature
(
CHECK_STREAM
);
parameters
.
append
(
ftp
);
c
=
READ
();
}
}
else
{
PUSH
(
c
);
}
EXPECT
(
'L'
);
ClassType
*
super
=
ClassType
::
parse_generic_signature
(
CHECK_STREAM
);
GrowableArray
<
ClassType
*>
signatures
(
2
);
while
(
!
STREAM
->
at_end
())
{
EXPECT
(
'L'
);
ClassType
*
iface
=
ClassType
::
parse_generic_signature
(
CHECK_STREAM
);
signatures
.
append
(
iface
);
}
EXPECT_END
();
return
new
ClassDescriptor
(
parameters
,
super
,
signatures
);
}
#ifndef PRODUCT
void
ClassDescriptor
::
print_on
(
outputStream
*
str
)
const
{
str
->
indent
().
print_cr
(
"ClassDescriptor {"
);
{
streamIndentor
si
(
str
);
if
(
_type_parameters
.
length
()
>
0
)
{
str
->
indent
().
print_cr
(
"Formals {"
);
{
streamIndentor
si
(
str
);
for
(
int
i
=
0
;
i
<
_type_parameters
.
length
();
++
i
)
{
_type_parameters
.
at
(
i
)
->
print_on
(
str
);
}
}
str
->
indent
().
print_cr
(
"}"
);
}
if
(
_super
!=
NULL
)
{
str
->
indent
().
print_cr
(
"Superclass: "
);
{
streamIndentor
si
(
str
);
_super
->
print_on
(
str
);
}
}
if
(
_interfaces
.
length
()
>
0
)
{
str
->
indent
().
print_cr
(
"SuperInterfaces: {"
);
{
streamIndentor
si
(
str
);
for
(
int
i
=
0
;
i
<
_interfaces
.
length
();
++
i
)
{
_interfaces
.
at
(
i
)
->
print_on
(
str
);
}
}
str
->
indent
().
print_cr
(
"}"
);
}
if
(
_outer_method
!=
NULL
)
{
str
->
indent
().
print_cr
(
"Outer Method: {"
);
{
streamIndentor
si
(
str
);
_outer_method
->
print_on
(
str
);
}
str
->
indent
().
print_cr
(
"}"
);
}
if
(
_outer_class
!=
NULL
)
{
str
->
indent
().
print_cr
(
"Outer Class: {"
);
{
streamIndentor
si
(
str
);
_outer_class
->
print_on
(
str
);
}
str
->
indent
().
print_cr
(
"}"
);
}
}
str
->
indent
().
print_cr
(
"}"
);
}
#endif // ndef PRODUCT
ClassType
*
ClassDescriptor
::
interface_desc
(
Symbol
*
sym
)
{
for
(
int
i
=
0
;
i
<
_interfaces
.
length
();
++
i
)
{
if
(
_interfaces
.
at
(
i
)
->
identifier
()
->
equals
(
sym
))
{
return
_interfaces
.
at
(
i
);
}
}
if
(
VerifyGenericSignatures
)
{
fatal
(
"Did not find expected interface"
);
}
return
NULL
;
}
void
ClassDescriptor
::
bind_variables_to_parameters
()
{
if
(
_outer_class
!=
NULL
)
{
_outer_class
->
bind_variables_to_parameters
();
}
if
(
_outer_method
!=
NULL
)
{
_outer_method
->
bind_variables_to_parameters
();
}
for
(
int
i
=
0
;
i
<
_type_parameters
.
length
();
++
i
)
{
_type_parameters
.
at
(
i
)
->
bind_variables_to_parameters
(
this
,
i
);
}
if
(
_super
!=
NULL
)
{
_super
->
bind_variables_to_parameters
(
this
);
}
for
(
int
i
=
0
;
i
<
_interfaces
.
length
();
++
i
)
{
_interfaces
.
at
(
i
)
->
bind_variables_to_parameters
(
this
);
}
}
ClassDescriptor
*
ClassDescriptor
::
canonicalize
(
Context
*
ctx
)
{
GrowableArray
<
TypeParameter
*>
type_params
(
_type_parameters
.
length
());
for
(
int
i
=
0
;
i
<
_type_parameters
.
length
();
++
i
)
{
type_params
.
append
(
_type_parameters
.
at
(
i
)
->
canonicalize
(
ctx
,
0
));
}
ClassDescriptor
*
outer
=
_outer_class
==
NULL
?
NULL
:
_outer_class
->
canonicalize
(
ctx
);
ClassType
*
super
=
_super
==
NULL
?
NULL
:
_super
->
canonicalize
(
ctx
,
0
);
GrowableArray
<
ClassType
*>
interfaces
(
_interfaces
.
length
());
for
(
int
i
=
0
;
i
<
_interfaces
.
length
();
++
i
)
{
interfaces
.
append
(
_interfaces
.
at
(
i
)
->
canonicalize
(
ctx
,
0
));
}
MethodDescriptor
*
md
=
_outer_method
==
NULL
?
NULL
:
_outer_method
->
canonicalize
(
ctx
);
return
new
ClassDescriptor
(
type_params
,
super
,
interfaces
,
outer
,
md
);
}
u2
ClassDescriptor
::
get_outer_class_index
(
InstanceKlass
*
klass
,
TRAPS
)
{
int
inner_index
=
InstanceKlass
::
inner_class_inner_class_info_offset
;
int
outer_index
=
InstanceKlass
::
inner_class_outer_class_info_offset
;
int
name_offset
=
InstanceKlass
::
inner_class_inner_name_offset
;
int
next_offset
=
InstanceKlass
::
inner_class_next_offset
;
if
(
klass
->
inner_classes
()
==
NULL
||
klass
->
inner_classes
()
->
length
()
==
0
)
{
// No inner class info => no declaring class
return
0
;
}
Array
<
u2
>*
i_icls
=
klass
->
inner_classes
();
ConstantPool
*
i_cp
=
klass
->
constants
();
int
i_length
=
i_icls
->
length
();
// Find inner_klass attribute
for
(
int
i
=
0
;
i
+
next_offset
<
i_length
;
i
+=
next_offset
)
{
u2
ioff
=
i_icls
->
at
(
i
+
inner_index
);
u2
ooff
=
i_icls
->
at
(
i
+
outer_index
);
u2
noff
=
i_icls
->
at
(
i
+
name_offset
);
if
(
ioff
!=
0
)
{
// Check to see if the name matches the class we're looking for
// before attempting to find the class.
if
(
i_cp
->
klass_name_at_matches
(
klass
,
ioff
)
&&
ooff
!=
0
)
{
return
ooff
;
}
}
}
// It may be anonymous; try for that.
u2
encl_method_class_idx
=
klass
->
enclosing_method_class_index
();
if
(
encl_method_class_idx
!=
0
)
{
return
encl_method_class_idx
;
}
return
0
;
}
MethodDescriptor
*
MethodDescriptor
::
parse_generic_signature
(
Method
*
m
,
ClassDescriptor
*
outer
)
{
Symbol
*
generic_sig
=
m
->
generic_signature
();
MethodDescriptor
*
md
=
NULL
;
if
(
generic_sig
==
NULL
||
(
md
=
parse_generic_signature
(
generic_sig
,
outer
))
==
NULL
)
{
md
=
parse_generic_signature
(
m
->
signature
(),
outer
);
}
assert
(
md
!=
NULL
,
"Could not parse method signature"
);
md
->
bind_variables_to_parameters
();
return
md
;
}
MethodDescriptor
*
MethodDescriptor
::
parse_generic_signature
(
Symbol
*
sym
,
ClassDescriptor
*
outer
)
{
DescriptorStream
ds
(
sym
);
DescriptorStream
*
STREAM
=
&
ds
;
GrowableArray
<
TypeParameter
*>
params
(
8
);
char
c
=
READ
();
if
(
c
==
'<'
)
{
c
=
READ
();
while
(
c
!=
'>'
)
{
PUSH
(
c
);
TypeParameter
*
ftp
=
TypeParameter
::
parse_generic_signature
(
CHECK_STREAM
);
params
.
append
(
ftp
);
c
=
READ
();
}
}
else
{
PUSH
(
c
);
}
EXPECT
(
'('
);
GrowableArray
<
Type
*>
parameters
(
8
);
c
=
READ
();
while
(
c
!=
')'
)
{
PUSH
(
c
);
Type
*
arg
=
Type
::
parse_generic_signature
(
CHECK_STREAM
);
parameters
.
append
(
arg
);
c
=
READ
();
}
Type
*
rt
=
Type
::
parse_generic_signature
(
CHECK_STREAM
);
GrowableArray
<
Type
*>
throws
;
while
(
!
STREAM
->
at_end
())
{
EXPECT
(
'^'
);
Type
*
spec
=
Type
::
parse_generic_signature
(
CHECK_STREAM
);
throws
.
append
(
spec
);
}
return
new
MethodDescriptor
(
params
,
outer
,
parameters
,
rt
,
throws
);
}
void
MethodDescriptor
::
bind_variables_to_parameters
()
{
for
(
int
i
=
0
;
i
<
_type_parameters
.
length
();
++
i
)
{
_type_parameters
.
at
(
i
)
->
bind_variables_to_parameters
(
this
,
i
);
}
for
(
int
i
=
0
;
i
<
_parameters
.
length
();
++
i
)
{
_parameters
.
at
(
i
)
->
bind_variables_to_parameters
(
this
);
}
_return_type
->
bind_variables_to_parameters
(
this
);
for
(
int
i
=
0
;
i
<
_throws
.
length
();
++
i
)
{
_throws
.
at
(
i
)
->
bind_variables_to_parameters
(
this
);
}
}
bool
MethodDescriptor
::
covariant_match
(
MethodDescriptor
*
other
,
Context
*
ctx
)
{
if
(
_parameters
.
length
()
==
other
->
_parameters
.
length
())
{
for
(
int
i
=
0
;
i
<
_parameters
.
length
();
++
i
)
{
if
(
!
_parameters
.
at
(
i
)
->
covariant_match
(
other
->
_parameters
.
at
(
i
),
ctx
))
{
return
false
;
}
}
if
(
_return_type
->
as_primitive
()
!=
NULL
)
{
return
_return_type
->
covariant_match
(
other
->
_return_type
,
ctx
);
}
else
{
// return type is a reference
return
other
->
_return_type
->
as_class
()
!=
NULL
||
other
->
_return_type
->
as_variable
()
!=
NULL
||
other
->
_return_type
->
as_array
()
!=
NULL
;
}
}
else
{
return
false
;
}
}
MethodDescriptor
*
MethodDescriptor
::
canonicalize
(
Context
*
ctx
)
{
GrowableArray
<
TypeParameter
*>
type_params
(
_type_parameters
.
length
());
for
(
int
i
=
0
;
i
<
_type_parameters
.
length
();
++
i
)
{
type_params
.
append
(
_type_parameters
.
at
(
i
)
->
canonicalize
(
ctx
,
0
));
}
ClassDescriptor
*
outer
=
_outer_class
==
NULL
?
NULL
:
_outer_class
->
canonicalize
(
ctx
);
GrowableArray
<
Type
*>
params
(
_parameters
.
length
());
for
(
int
i
=
0
;
i
<
_parameters
.
length
();
++
i
)
{
params
.
append
(
_parameters
.
at
(
i
)
->
canonicalize
(
ctx
,
0
));
}
Type
*
rt
=
_return_type
->
canonicalize
(
ctx
,
0
);
GrowableArray
<
Type
*>
throws
(
_throws
.
length
());
for
(
int
i
=
0
;
i
<
_throws
.
length
();
++
i
)
{
throws
.
append
(
_throws
.
at
(
i
)
->
canonicalize
(
ctx
,
0
));
}
return
new
MethodDescriptor
(
type_params
,
outer
,
params
,
rt
,
throws
);
}
#ifndef PRODUCT
TempNewSymbol
MethodDescriptor
::
reify_signature
(
Context
*
ctx
,
TRAPS
)
{
stringStream
ss
(
256
);
ss
.
print
(
"("
);
for
(
int
i
=
0
;
i
<
_parameters
.
length
();
++
i
)
{
_parameters
.
at
(
i
)
->
reify_signature
(
&
ss
,
ctx
);
}
ss
.
print
(
")"
);
_return_type
->
reify_signature
(
&
ss
,
ctx
);
return
SymbolTable
::
new_symbol
(
ss
.
base
(),
(
int
)
ss
.
size
(),
THREAD
);
}
void
MethodDescriptor
::
print_on
(
outputStream
*
str
)
const
{
str
->
indent
().
print_cr
(
"MethodDescriptor {"
);
{
streamIndentor
si
(
str
);
if
(
_type_parameters
.
length
()
>
0
)
{
str
->
indent
().
print_cr
(
"Formals: {"
);
{
streamIndentor
si
(
str
);
for
(
int
i
=
0
;
i
<
_type_parameters
.
length
();
++
i
)
{
_type_parameters
.
at
(
i
)
->
print_on
(
str
);
}
}
str
->
indent
().
print_cr
(
"}"
);
}
str
->
indent
().
print_cr
(
"Parameters: {"
);
{
streamIndentor
si
(
str
);
for
(
int
i
=
0
;
i
<
_parameters
.
length
();
++
i
)
{
_parameters
.
at
(
i
)
->
print_on
(
str
);
}
}
str
->
indent
().
print_cr
(
"}"
);
str
->
indent
().
print_cr
(
"Return Type: "
);
{
streamIndentor
si
(
str
);
_return_type
->
print_on
(
str
);
}
if
(
_throws
.
length
()
>
0
)
{
str
->
indent
().
print_cr
(
"Throws: {"
);
{
streamIndentor
si
(
str
);
for
(
int
i
=
0
;
i
<
_throws
.
length
();
++
i
)
{
_throws
.
at
(
i
)
->
print_on
(
str
);
}
}
str
->
indent
().
print_cr
(
"}"
);
}
}
str
->
indent
().
print_cr
(
"}"
);
}
#endif // ndef PRODUCT
TypeParameter
*
TypeParameter
::
parse_generic_signature
(
DescriptorStream
*
STREAM
)
{
STREAM
->
set_mark
();
char
c
=
READ
();
while
(
c
!=
':'
)
{
c
=
READ
();
}
Identifier
*
id
=
STREAM
->
identifier_from_mark
();
ClassType
*
class_bound
=
NULL
;
GrowableArray
<
ClassType
*>
interface_bounds
(
8
);
c
=
READ
();
if
(
c
!=
'>'
)
{
if
(
c
!=
':'
)
{
EXPECTED
(
c
,
'L'
);
class_bound
=
ClassType
::
parse_generic_signature
(
CHECK_STREAM
);
c
=
READ
();
}
while
(
c
==
':'
)
{
EXPECT
(
'L'
);
ClassType
*
fts
=
ClassType
::
parse_generic_signature
(
CHECK_STREAM
);
interface_bounds
.
append
(
fts
);
c
=
READ
();
}
}
PUSH
(
c
);
return
new
TypeParameter
(
id
,
class_bound
,
interface_bounds
);
}
void
TypeParameter
::
bind_variables_to_parameters
(
Descriptor
*
sig
,
int
position
)
{
if
(
_class_bound
!=
NULL
)
{
_class_bound
->
bind_variables_to_parameters
(
sig
);
}
for
(
int
i
=
0
;
i
<
_interface_bounds
.
length
();
++
i
)
{
_interface_bounds
.
at
(
i
)
->
bind_variables_to_parameters
(
sig
);
}
_position
=
position
;
}
Type
*
TypeParameter
::
resolve
(
Context
*
ctx
,
int
inner_depth
,
int
ctx_depth
)
{
if
(
inner_depth
==
-
1
)
{
// This indicates that the parameter is a method type parameter, which
// isn't resolveable using the class hierarchy context
return
bound
();
}
ClassType
*
provider
=
ctx
->
at_depth
(
ctx_depth
);
if
(
provider
!=
NULL
)
{
for
(
int
i
=
0
;
i
<
inner_depth
&&
provider
!=
NULL
;
++
i
)
{
provider
=
provider
->
outer_class
();
}
if
(
provider
!=
NULL
)
{
TypeArgument
*
arg
=
provider
->
type_argument_at
(
_position
);
if
(
arg
!=
NULL
)
{
Type
*
value
=
arg
->
lower_bound
();
return
value
->
canonicalize
(
ctx
,
ctx_depth
+
1
);
}
}
}
return
bound
();
}
TypeParameter
*
TypeParameter
::
canonicalize
(
Context
*
ctx
,
int
ctx_depth
)
{
ClassType
*
bound
=
_class_bound
==
NULL
?
NULL
:
_class_bound
->
canonicalize
(
ctx
,
ctx_depth
);
GrowableArray
<
ClassType
*>
ifaces
(
_interface_bounds
.
length
());
for
(
int
i
=
0
;
i
<
_interface_bounds
.
length
();
++
i
)
{
ifaces
.
append
(
_interface_bounds
.
at
(
i
)
->
canonicalize
(
ctx
,
ctx_depth
));
}
TypeParameter
*
ret
=
new
TypeParameter
(
_identifier
,
bound
,
ifaces
);
ret
->
_position
=
_position
;
return
ret
;
}
ClassType
*
TypeParameter
::
bound
()
{
if
(
_class_bound
!=
NULL
)
{
return
_class_bound
;
}
if
(
_interface_bounds
.
length
()
==
1
)
{
return
_interface_bounds
.
at
(
0
);
}
return
ClassType
::
java_lang_Object
();
// TODO: investigate this case
}
#ifndef PRODUCT
void
TypeParameter
::
print_on
(
outputStream
*
str
)
const
{
str
->
indent
().
print_cr
(
"Formal: {"
);
{
streamIndentor
si
(
str
);
str
->
indent
().
print
(
"Identifier: "
);
_identifier
->
print_on
(
str
);
str
->
print_cr
(
""
);
if
(
_class_bound
!=
NULL
)
{
str
->
indent
().
print_cr
(
"Class Bound: "
);
streamIndentor
si
(
str
);
_class_bound
->
print_on
(
str
);
}
if
(
_interface_bounds
.
length
()
>
0
)
{
str
->
indent
().
print_cr
(
"Interface Bounds: {"
);
{
streamIndentor
si
(
str
);
for
(
int
i
=
0
;
i
<
_interface_bounds
.
length
();
++
i
)
{
_interface_bounds
.
at
(
i
)
->
print_on
(
str
);
}
}
str
->
indent
().
print_cr
(
"}"
);
}
str
->
indent
().
print_cr
(
"Ordinal Position: %d"
,
_position
);
}
str
->
indent
().
print_cr
(
"}"
);
}
#endif // ndef PRODUCT
Type
*
Type
::
parse_generic_signature
(
DescriptorStream
*
STREAM
)
{
char
c
=
READ
();
switch
(
c
)
{
case
'L'
:
return
ClassType
::
parse_generic_signature
(
CHECK_STREAM
);
case
'T'
:
return
TypeVariable
::
parse_generic_signature
(
CHECK_STREAM
);
case
'['
:
return
ArrayType
::
parse_generic_signature
(
CHECK_STREAM
);
default:
return
new
PrimitiveType
(
c
);
}
}
Identifier
*
ClassType
::
parse_generic_signature_simple
(
GrowableArray
<
TypeArgument
*>*
args
,
bool
*
has_inner
,
DescriptorStream
*
STREAM
)
{
STREAM
->
set_mark
();
char
c
=
READ
();
while
(
c
!=
';'
&&
c
!=
'.'
&&
c
!=
'<'
)
{
c
=
READ
();
}
Identifier
*
id
=
STREAM
->
identifier_from_mark
();
if
(
c
==
'<'
)
{
c
=
READ
();
while
(
c
!=
'>'
)
{
PUSH
(
c
);
TypeArgument
*
arg
=
TypeArgument
::
parse_generic_signature
(
CHECK_STREAM
);
args
->
append
(
arg
);
c
=
READ
();
}
c
=
READ
();
}
*
has_inner
=
(
c
==
'.'
);
if
(
!
(
*
has_inner
))
{
EXPECTED
(
c
,
';'
);
}
return
id
;
}
ClassType
*
ClassType
::
parse_generic_signature
(
DescriptorStream
*
STREAM
)
{
return
parse_generic_signature
(
NULL
,
CHECK_STREAM
);
}
ClassType
*
ClassType
::
parse_generic_signature
(
ClassType
*
outer
,
DescriptorStream
*
STREAM
)
{
GrowableArray
<
TypeArgument
*>
args
;
ClassType
*
gct
=
NULL
;
bool
has_inner
=
false
;
Identifier
*
id
=
parse_generic_signature_simple
(
&
args
,
&
has_inner
,
STREAM
);
if
(
id
!=
NULL
)
{
gct
=
new
ClassType
(
id
,
args
,
outer
);
if
(
has_inner
)
{
gct
=
parse_generic_signature
(
gct
,
CHECK_STREAM
);
}
}
return
gct
;
}
ClassType
*
ClassType
::
from_symbol
(
Symbol
*
sym
)
{
assert
(
sym
!=
NULL
,
"Must not be null"
);
GrowableArray
<
TypeArgument
*>
args
;
Identifier
*
id
=
new
Identifier
(
sym
,
0
,
sym
->
utf8_length
());
return
new
ClassType
(
id
,
args
,
NULL
);
}
ClassType
*
ClassType
::
java_lang_Object
()
{
return
from_symbol
(
vmSymbols
::
java_lang_Object
());
}
void
ClassType
::
bind_variables_to_parameters
(
Descriptor
*
sig
)
{
for
(
int
i
=
0
;
i
<
_type_arguments
.
length
();
++
i
)
{
_type_arguments
.
at
(
i
)
->
bind_variables_to_parameters
(
sig
);
}
if
(
_outer_class
!=
NULL
)
{
_outer_class
->
bind_variables_to_parameters
(
sig
);
}
}
TypeArgument
*
ClassType
::
type_argument_at
(
int
i
)
{
if
(
i
>=
0
&&
i
<
_type_arguments
.
length
())
{
return
_type_arguments
.
at
(
i
);
}
else
{
return
NULL
;
}
}
#ifndef PRODUCT
void
ClassType
::
reify_signature
(
stringStream
*
ss
,
Context
*
ctx
)
{
ss
->
print
(
"L"
);
_identifier
->
print_on
(
ss
);
ss
->
print
(
";"
);
}
void
ClassType
::
print_on
(
outputStream
*
str
)
const
{
str
->
indent
().
print_cr
(
"Class {"
);
{
streamIndentor
si
(
str
);
str
->
indent
().
print
(
"Name: "
);
_identifier
->
print_on
(
str
);
str
->
print_cr
(
""
);
if
(
_type_arguments
.
length
()
!=
0
)
{
str
->
indent
().
print_cr
(
"Type Arguments: {"
);
{
streamIndentor
si
(
str
);
for
(
int
j
=
0
;
j
<
_type_arguments
.
length
();
++
j
)
{
_type_arguments
.
at
(
j
)
->
print_on
(
str
);
}
}
str
->
indent
().
print_cr
(
"}"
);
}
if
(
_outer_class
!=
NULL
)
{
str
->
indent
().
print_cr
(
"Outer Class: "
);
streamIndentor
sir
(
str
);
_outer_class
->
print_on
(
str
);
}
}
str
->
indent
().
print_cr
(
"}"
);
}
#endif // ndef PRODUCT
bool
ClassType
::
covariant_match
(
Type
*
other
,
Context
*
ctx
)
{
if
(
other
==
this
)
{
return
true
;
}
TypeVariable
*
variable
=
other
->
as_variable
();
if
(
variable
!=
NULL
)
{
other
=
variable
->
resolve
(
ctx
,
0
);
}
ClassType
*
outer
=
outer_class
();
ClassType
*
other_class
=
other
->
as_class
();
if
(
other_class
==
NULL
||
(
outer
==
NULL
)
!=
(
other_class
->
outer_class
()
==
NULL
))
{
return
false
;
}
if
(
!
_identifier
->
equals
(
other_class
->
_identifier
))
{
return
false
;
}
if
(
outer
!=
NULL
&&
!
outer
->
covariant_match
(
other_class
->
outer_class
(),
ctx
))
{
return
false
;
}
return
true
;
}
ClassType
*
ClassType
::
canonicalize
(
Context
*
ctx
,
int
ctx_depth
)
{
GrowableArray
<
TypeArgument
*>
args
(
_type_arguments
.
length
());
for
(
int
i
=
0
;
i
<
_type_arguments
.
length
();
++
i
)
{
args
.
append
(
_type_arguments
.
at
(
i
)
->
canonicalize
(
ctx
,
ctx_depth
));
}
ClassType
*
outer
=
_outer_class
==
NULL
?
NULL
:
_outer_class
->
canonicalize
(
ctx
,
ctx_depth
);
return
new
ClassType
(
_identifier
,
args
,
outer
);
}
TypeVariable
*
TypeVariable
::
parse_generic_signature
(
DescriptorStream
*
STREAM
)
{
STREAM
->
set_mark
();
char
c
=
READ
();
while
(
c
!=
';'
)
{
c
=
READ
();
}
Identifier
*
id
=
STREAM
->
identifier_from_mark
();
return
new
TypeVariable
(
id
);
}
void
TypeVariable
::
bind_variables_to_parameters
(
Descriptor
*
sig
)
{
_parameter
=
sig
->
find_type_parameter
(
_id
,
&
_inner_depth
);
if
(
VerifyGenericSignatures
&&
_parameter
==
NULL
)
{
fatal
(
"Could not find formal parameter"
);
}
}
Type
*
TypeVariable
::
resolve
(
Context
*
ctx
,
int
ctx_depth
)
{
if
(
parameter
()
!=
NULL
)
{
return
parameter
()
->
resolve
(
ctx
,
inner_depth
(),
ctx_depth
);
}
else
{
if
(
VerifyGenericSignatures
)
{
fatal
(
"Type variable matches no parameter"
);
}
return
NULL
;
}
}
bool
TypeVariable
::
covariant_match
(
Type
*
other
,
Context
*
ctx
)
{
if
(
other
==
this
)
{
return
true
;
}
Context
my_context
(
NULL
);
// empty, results in erasure
Type
*
my_type
=
resolve
(
&
my_context
,
0
);
if
(
my_type
==
NULL
)
{
return
false
;
}
return
my_type
->
covariant_match
(
other
,
ctx
);
}
Type
*
TypeVariable
::
canonicalize
(
Context
*
ctx
,
int
ctx_depth
)
{
return
resolve
(
ctx
,
ctx_depth
);
}
#ifndef PRODUCT
void
TypeVariable
::
reify_signature
(
stringStream
*
ss
,
Context
*
ctx
)
{
Type
*
type
=
resolve
(
ctx
,
0
);
if
(
type
!=
NULL
)
{
type
->
reify_signature
(
ss
,
ctx
);
}
}
void
TypeVariable
::
print_on
(
outputStream
*
str
)
const
{
str
->
indent
().
print_cr
(
"Type Variable {"
);
{
streamIndentor
si
(
str
);
str
->
indent
().
print
(
"Name: "
);
_id
->
print_on
(
str
);
str
->
print_cr
(
""
);
str
->
indent
().
print_cr
(
"Inner depth: %d"
,
_inner_depth
);
}
str
->
indent
().
print_cr
(
"}"
);
}
#endif // ndef PRODUCT
ArrayType
*
ArrayType
::
parse_generic_signature
(
DescriptorStream
*
STREAM
)
{
Type
*
base
=
Type
::
parse_generic_signature
(
CHECK_STREAM
);
return
new
ArrayType
(
base
);
}
void
ArrayType
::
bind_variables_to_parameters
(
Descriptor
*
sig
)
{
assert
(
_base
!=
NULL
,
"Invalid base"
);
_base
->
bind_variables_to_parameters
(
sig
);
}
bool
ArrayType
::
covariant_match
(
Type
*
other
,
Context
*
ctx
)
{
assert
(
_base
!=
NULL
,
"Invalid base"
);
if
(
other
==
this
)
{
return
true
;
}
ArrayType
*
other_array
=
other
->
as_array
();
return
(
other_array
!=
NULL
&&
_base
->
covariant_match
(
other_array
->
_base
,
ctx
));
}
ArrayType
*
ArrayType
::
canonicalize
(
Context
*
ctx
,
int
ctx_depth
)
{
assert
(
_base
!=
NULL
,
"Invalid base"
);
return
new
ArrayType
(
_base
->
canonicalize
(
ctx
,
ctx_depth
));
}
#ifndef PRODUCT
void
ArrayType
::
reify_signature
(
stringStream
*
ss
,
Context
*
ctx
)
{
assert
(
_base
!=
NULL
,
"Invalid base"
);
ss
->
print
(
"["
);
_base
->
reify_signature
(
ss
,
ctx
);
}
void
ArrayType
::
print_on
(
outputStream
*
str
)
const
{
str
->
indent
().
print_cr
(
"Array {"
);
{
streamIndentor
si
(
str
);
_base
->
print_on
(
str
);
}
str
->
indent
().
print_cr
(
"}"
);
}
#endif // ndef PRODUCT
bool
PrimitiveType
::
covariant_match
(
Type
*
other
,
Context
*
ctx
)
{
PrimitiveType
*
other_prim
=
other
->
as_primitive
();
return
(
other_prim
!=
NULL
&&
_type
==
other_prim
->
_type
);
}
PrimitiveType
*
PrimitiveType
::
canonicalize
(
Context
*
ctx
,
int
ctxd
)
{
return
this
;
}
#ifndef PRODUCT
void
PrimitiveType
::
reify_signature
(
stringStream
*
ss
,
Context
*
ctx
)
{
ss
->
print
(
"%c"
,
_type
);
}
void
PrimitiveType
::
print_on
(
outputStream
*
str
)
const
{
str
->
indent
().
print_cr
(
"Primitive: '%c'"
,
_type
);
}
#endif // ndef PRODUCT
void
PrimitiveType
::
bind_variables_to_parameters
(
Descriptor
*
sig
)
{
}
TypeArgument
*
TypeArgument
::
parse_generic_signature
(
DescriptorStream
*
STREAM
)
{
char
c
=
READ
();
Type
*
type
=
NULL
;
switch
(
c
)
{
case
'*'
:
return
new
TypeArgument
(
ClassType
::
java_lang_Object
(),
NULL
);
break
;
default:
PUSH
(
c
);
// fall-through
case
'+'
:
case
'-'
:
type
=
Type
::
parse_generic_signature
(
CHECK_STREAM
);
if
(
c
==
'+'
)
{
return
new
TypeArgument
(
type
,
NULL
);
}
else
if
(
c
==
'-'
)
{
return
new
TypeArgument
(
ClassType
::
java_lang_Object
(),
type
);
}
else
{
return
new
TypeArgument
(
type
,
type
);
}
}
}
void
TypeArgument
::
bind_variables_to_parameters
(
Descriptor
*
sig
)
{
assert
(
_lower_bound
!=
NULL
,
"Invalid lower bound"
);
_lower_bound
->
bind_variables_to_parameters
(
sig
);
if
(
_upper_bound
!=
NULL
&&
_upper_bound
!=
_lower_bound
)
{
_upper_bound
->
bind_variables_to_parameters
(
sig
);
}
}
bool
TypeArgument
::
covariant_match
(
TypeArgument
*
other
,
Context
*
ctx
)
{
assert
(
_lower_bound
!=
NULL
,
"Invalid lower bound"
);
if
(
other
==
this
)
{
return
true
;
}
if
(
!
_lower_bound
->
covariant_match
(
other
->
lower_bound
(),
ctx
))
{
return
false
;
}
return
true
;
}
TypeArgument
*
TypeArgument
::
canonicalize
(
Context
*
ctx
,
int
ctx_depth
)
{
assert
(
_lower_bound
!=
NULL
,
"Invalid lower bound"
);
Type
*
lower
=
_lower_bound
->
canonicalize
(
ctx
,
ctx_depth
);
Type
*
upper
=
NULL
;
if
(
_upper_bound
==
_lower_bound
)
{
upper
=
lower
;
}
else
if
(
_upper_bound
!=
NULL
)
{
upper
=
_upper_bound
->
canonicalize
(
ctx
,
ctx_depth
);
}
return
new
TypeArgument
(
lower
,
upper
);
}
#ifndef PRODUCT
void
TypeArgument
::
print_on
(
outputStream
*
str
)
const
{
str
->
indent
().
print_cr
(
"TypeArgument {"
);
{
streamIndentor
si
(
str
);
if
(
_lower_bound
!=
NULL
)
{
str
->
indent
().
print
(
"Lower bound: "
);
_lower_bound
->
print_on
(
str
);
}
if
(
_upper_bound
!=
NULL
)
{
str
->
indent
().
print
(
"Upper bound: "
);
_upper_bound
->
print_on
(
str
);
}
}
str
->
indent
().
print_cr
(
"}"
);
}
#endif // ndef PRODUCT
void
Context
::
Mark
::
destroy
()
{
if
(
is_active
())
{
_context
->
reset_to_mark
(
_marked_size
);
}
deactivate
();
}
void
Context
::
apply_type_arguments
(
InstanceKlass
*
current
,
InstanceKlass
*
super
,
TRAPS
)
{
assert
(
_cache
!=
NULL
,
"Cannot use an empty context"
);
ClassType
*
spec
=
NULL
;
if
(
current
!=
NULL
)
{
ClassDescriptor
*
descriptor
=
_cache
->
descriptor_for
(
current
,
CHECK
);
if
(
super
==
current
->
super
())
{
spec
=
descriptor
->
super
();
}
else
{
spec
=
descriptor
->
interface_desc
(
super
->
name
());
}
if
(
spec
!=
NULL
)
{
_type_arguments
.
push
(
spec
);
}
}
}
void
Context
::
reset_to_mark
(
int
size
)
{
_type_arguments
.
trunc_to
(
size
);
}
ClassType
*
Context
::
at_depth
(
int
i
)
const
{
if
(
i
<
_type_arguments
.
length
())
{
return
_type_arguments
.
at
(
_type_arguments
.
length
()
-
1
-
i
);
}
return
NULL
;
}
#ifndef PRODUCT
void
Context
::
print_on
(
outputStream
*
str
)
const
{
str
->
indent
().
print_cr
(
"Context {"
);
for
(
int
i
=
0
;
i
<
_type_arguments
.
length
();
++
i
)
{
streamIndentor
si
(
str
);
str
->
indent
().
print
(
"leval %d: "
,
i
);
ClassType
*
ct
=
at_depth
(
i
);
if
(
ct
==
NULL
)
{
str
->
print_cr
(
"<empty>"
);
continue
;
}
else
{
str
->
print_cr
(
"{"
);
}
for
(
int
j
=
0
;
j
<
ct
->
type_arguments_length
();
++
j
)
{
streamIndentor
si
(
str
);
TypeArgument
*
ta
=
ct
->
type_argument_at
(
j
);
Type
*
bound
=
ta
->
lower_bound
();
bound
->
print_on
(
str
);
}
str
->
indent
().
print_cr
(
"}"
);
}
str
->
indent
().
print_cr
(
"}"
);
}
#endif // ndef PRODUCT
ClassDescriptor
*
DescriptorCache
::
descriptor_for
(
InstanceKlass
*
ik
,
TRAPS
)
{
ClassDescriptor
**
existing
=
_class_descriptors
.
get
(
ik
);
if
(
existing
==
NULL
)
{
ClassDescriptor
*
cd
=
ClassDescriptor
::
parse_generic_signature
(
ik
,
CHECK_NULL
);
_class_descriptors
.
put
(
ik
,
cd
);
return
cd
;
}
else
{
return
*
existing
;
}
}
MethodDescriptor
*
DescriptorCache
::
descriptor_for
(
Method
*
mh
,
ClassDescriptor
*
cd
,
TRAPS
)
{
assert
(
mh
!=
NULL
&&
cd
!=
NULL
,
"Should not be NULL"
);
MethodDescriptor
**
existing
=
_method_descriptors
.
get
(
mh
);
if
(
existing
==
NULL
)
{
MethodDescriptor
*
md
=
MethodDescriptor
::
parse_generic_signature
(
mh
,
cd
);
_method_descriptors
.
put
(
mh
,
md
);
return
md
;
}
else
{
return
*
existing
;
}
}
MethodDescriptor
*
DescriptorCache
::
descriptor_for
(
Method
*
mh
,
TRAPS
)
{
ClassDescriptor
*
cd
=
descriptor_for
(
InstanceKlass
::
cast
(
mh
->
method_holder
()),
CHECK_NULL
);
return
descriptor_for
(
mh
,
cd
,
THREAD
);
}
}
// namespace generic
src/share/vm/classfile/genericSignatures.hpp
已删除
100644 → 0
浏览文件 @
13b030b0
/*
* Copyright (c) 2012, 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.
*
*/
#ifndef SHARE_VM_CLASSFILE_GENERICSIGNATURES_HPP
#define SHARE_VM_CLASSFILE_GENERICSIGNATURES_HPP
#include "classfile/symbolTable.hpp"
#include "memory/allocation.hpp"
#include "runtime/signature.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/resourceHash.hpp"
class
stringStream
;
namespace
generic
{
class
Identifier
;
class
ClassDescriptor
;
class
MethodDescriptor
;
class
TypeParameter
;
// a formal type parameter declared in generic signatures
class
TypeArgument
;
// The "type value" passed to fill parameters in supertypes
class
TypeVariable
;
// A usage of a type parameter as a value
/**
* Example:
*
* <T, V> class Foo extends Bar<String> { int m(V v) {} }
* ^^^^^^ ^^^^^^ ^^
* type parameters type argument type variable
*
* Note that a type variable could be passed as an argument too:
* <T, V> class Foo extends Bar<T> { int m(V v) {} }
* ^^^
* type argument's value is a type variable
*/
class
Type
;
class
ClassType
;
class
ArrayType
;
class
PrimitiveType
;
class
Context
;
class
DescriptorCache
;
class
DescriptorStream
;
class
Identifier
:
public
ResourceObj
{
private:
Symbol
*
_sym
;
int
_begin
;
int
_end
;
public:
Identifier
(
Symbol
*
sym
,
int
begin
,
int
end
)
:
_sym
(
sym
),
_begin
(
begin
),
_end
(
end
)
{}
bool
equals
(
Identifier
*
other
);
bool
equals
(
Symbol
*
sym
);
#ifndef PRODUCT
void
print_on
(
outputStream
*
str
)
const
;
#endif // ndef PRODUCT
};
class
Descriptor
:
public
ResourceObj
{
protected:
GrowableArray
<
TypeParameter
*>
_type_parameters
;
ClassDescriptor
*
_outer_class
;
Descriptor
(
GrowableArray
<
TypeParameter
*>&
params
,
ClassDescriptor
*
outer
)
:
_type_parameters
(
params
),
_outer_class
(
outer
)
{}
public:
ClassDescriptor
*
outer_class
()
{
return
_outer_class
;
}
void
set_outer_class
(
ClassDescriptor
*
sig
)
{
_outer_class
=
sig
;
}
virtual
ClassDescriptor
*
as_class_signature
()
{
return
NULL
;
}
virtual
MethodDescriptor
*
as_method_signature
()
{
return
NULL
;
}
bool
is_class_signature
()
{
return
as_class_signature
()
!=
NULL
;
}
bool
is_method_signature
()
{
return
as_method_signature
()
!=
NULL
;
}
GrowableArray
<
TypeParameter
*>&
type_parameters
()
{
return
_type_parameters
;
}
TypeParameter
*
find_type_parameter
(
Identifier
*
id
,
int
*
param_depth
);
virtual
void
bind_variables_to_parameters
()
=
0
;
#ifndef PRODUCT
virtual
void
print_on
(
outputStream
*
str
)
const
=
0
;
#endif
};
class
ClassDescriptor
:
public
Descriptor
{
private:
ClassType
*
_super
;
GrowableArray
<
ClassType
*>
_interfaces
;
MethodDescriptor
*
_outer_method
;
ClassDescriptor
(
GrowableArray
<
TypeParameter
*>&
ftp
,
ClassType
*
scs
,
GrowableArray
<
ClassType
*>&
sis
,
ClassDescriptor
*
outer_class
=
NULL
,
MethodDescriptor
*
outer_method
=
NULL
)
:
Descriptor
(
ftp
,
outer_class
),
_super
(
scs
),
_interfaces
(
sis
),
_outer_method
(
outer_method
)
{}
static
u2
get_outer_class_index
(
InstanceKlass
*
k
,
TRAPS
);
static
ClassDescriptor
*
parse_generic_signature
(
Klass
*
k
,
Symbol
*
original_name
,
TRAPS
);
public:
virtual
ClassDescriptor
*
as_class_signature
()
{
return
this
;
}
MethodDescriptor
*
outer_method
()
{
return
_outer_method
;
}
void
set_outer_method
(
MethodDescriptor
*
m
)
{
_outer_method
=
m
;
}
ClassType
*
super
()
{
return
_super
;
}
ClassType
*
interface_desc
(
Symbol
*
sym
);
static
ClassDescriptor
*
parse_generic_signature
(
Klass
*
k
,
TRAPS
);
static
ClassDescriptor
*
parse_generic_signature
(
Symbol
*
sym
);
// For use in superclass chains in positions where this is no generic info
static
ClassDescriptor
*
placeholder
(
InstanceKlass
*
klass
);
#ifndef PRODUCT
void
print_on
(
outputStream
*
str
)
const
;
#endif
ClassDescriptor
*
canonicalize
(
Context
*
ctx
);
// Linking sets the position index in any contained TypeVariable type
// to correspond to the location of that identifier in the formal type
// parameters.
void
bind_variables_to_parameters
();
};
class
MethodDescriptor
:
public
Descriptor
{
private:
GrowableArray
<
Type
*>
_parameters
;
Type
*
_return_type
;
GrowableArray
<
Type
*>
_throws
;
MethodDescriptor
(
GrowableArray
<
TypeParameter
*>&
ftp
,
ClassDescriptor
*
outer
,
GrowableArray
<
Type
*>&
sigs
,
Type
*
rt
,
GrowableArray
<
Type
*>&
throws
)
:
Descriptor
(
ftp
,
outer
),
_parameters
(
sigs
),
_return_type
(
rt
),
_throws
(
throws
)
{}
public:
static
MethodDescriptor
*
parse_generic_signature
(
Method
*
m
,
ClassDescriptor
*
outer
);
static
MethodDescriptor
*
parse_generic_signature
(
Symbol
*
sym
,
ClassDescriptor
*
outer
);
MethodDescriptor
*
as_method_signature
()
{
return
this
;
}
// Performs generic analysis on the method parameters to determine
// if both methods refer to the same argument types.
bool
covariant_match
(
MethodDescriptor
*
other
,
Context
*
ctx
);
// Returns a new method descriptor with all generic variables
// removed and replaced with whatever is indicated using the Context.
MethodDescriptor
*
canonicalize
(
Context
*
ctx
);
void
bind_variables_to_parameters
();
#ifndef PRODUCT
TempNewSymbol
reify_signature
(
Context
*
ctx
,
TRAPS
);
void
print_on
(
outputStream
*
str
)
const
;
#endif
};
class
TypeParameter
:
public
ResourceObj
{
private:
Identifier
*
_identifier
;
ClassType
*
_class_bound
;
GrowableArray
<
ClassType
*>
_interface_bounds
;
// The position is the ordinal location of the parameter within the
// formal parameter list (excluding outer classes). It is only set for
// formal type parameters that are associated with a class -- method
// type parameters are left as -1. When resolving a generic variable to
// find the actual type, this index is used to access the generic type
// argument in the provided context object.
int
_position
;
// Assigned during variable linking
TypeParameter
(
Identifier
*
id
,
ClassType
*
class_bound
,
GrowableArray
<
ClassType
*>&
interface_bounds
)
:
_identifier
(
id
),
_class_bound
(
class_bound
),
_interface_bounds
(
interface_bounds
),
_position
(
-
1
)
{}
public:
static
TypeParameter
*
parse_generic_signature
(
DescriptorStream
*
str
);
ClassType
*
bound
();
int
position
()
{
return
_position
;
}
void
bind_variables_to_parameters
(
Descriptor
*
sig
,
int
position
);
Identifier
*
identifier
()
{
return
_identifier
;
}
Type
*
resolve
(
Context
*
ctx
,
int
inner_depth
,
int
ctx_depth
);
TypeParameter
*
canonicalize
(
Context
*
ctx
,
int
ctx_depth
);
#ifndef PRODUCT
void
print_on
(
outputStream
*
str
)
const
;
#endif
};
class
Type
:
public
ResourceObj
{
public:
static
Type
*
parse_generic_signature
(
DescriptorStream
*
str
);
virtual
ClassType
*
as_class
()
{
return
NULL
;
}
virtual
TypeVariable
*
as_variable
()
{
return
NULL
;
}
virtual
ArrayType
*
as_array
()
{
return
NULL
;
}
virtual
PrimitiveType
*
as_primitive
()
{
return
NULL
;
}
virtual
bool
covariant_match
(
Type
*
gt
,
Context
*
ctx
)
=
0
;
virtual
Type
*
canonicalize
(
Context
*
ctx
,
int
ctx_depth
)
=
0
;
virtual
void
bind_variables_to_parameters
(
Descriptor
*
sig
)
=
0
;
#ifndef PRODUCT
virtual
void
reify_signature
(
stringStream
*
ss
,
Context
*
ctx
)
=
0
;
virtual
void
print_on
(
outputStream
*
str
)
const
=
0
;
#endif
};
class
ClassType
:
public
Type
{
friend
class
ClassDescriptor
;
protected:
Identifier
*
_identifier
;
GrowableArray
<
TypeArgument
*>
_type_arguments
;
ClassType
*
_outer_class
;
ClassType
(
Identifier
*
identifier
,
GrowableArray
<
TypeArgument
*>&
args
,
ClassType
*
outer
)
:
_identifier
(
identifier
),
_type_arguments
(
args
),
_outer_class
(
outer
)
{}
// Returns true if there are inner classes to read
static
Identifier
*
parse_generic_signature_simple
(
GrowableArray
<
TypeArgument
*>*
args
,
bool
*
has_inner
,
DescriptorStream
*
str
);
static
ClassType
*
parse_generic_signature
(
ClassType
*
outer
,
DescriptorStream
*
str
);
static
ClassType
*
from_symbol
(
Symbol
*
sym
);
public:
ClassType
*
as_class
()
{
return
this
;
}
static
ClassType
*
parse_generic_signature
(
DescriptorStream
*
str
);
static
ClassType
*
java_lang_Object
();
Identifier
*
identifier
()
{
return
_identifier
;
}
int
type_arguments_length
()
{
return
_type_arguments
.
length
();
}
TypeArgument
*
type_argument_at
(
int
i
);
virtual
ClassType
*
outer_class
()
{
return
_outer_class
;
}
bool
covariant_match
(
Type
*
gt
,
Context
*
ctx
);
ClassType
*
canonicalize
(
Context
*
ctx
,
int
context_depth
);
void
bind_variables_to_parameters
(
Descriptor
*
sig
);
#ifndef PRODUCT
void
reify_signature
(
stringStream
*
ss
,
Context
*
ctx
);
void
print_on
(
outputStream
*
str
)
const
;
#endif
};
class
TypeVariable
:
public
Type
{
private:
Identifier
*
_id
;
TypeParameter
*
_parameter
;
// assigned during linking
// how many steps "out" from inner classes, -1 if method
int
_inner_depth
;
TypeVariable
(
Identifier
*
id
)
:
_id
(
id
),
_parameter
(
NULL
),
_inner_depth
(
0
)
{}
public:
TypeVariable
*
as_variable
()
{
return
this
;
}
static
TypeVariable
*
parse_generic_signature
(
DescriptorStream
*
str
);
Identifier
*
identifier
()
{
return
_id
;
}
TypeParameter
*
parameter
()
{
return
_parameter
;
}
int
inner_depth
()
{
return
_inner_depth
;
}
void
bind_variables_to_parameters
(
Descriptor
*
sig
);
Type
*
resolve
(
Context
*
ctx
,
int
ctx_depth
);
bool
covariant_match
(
Type
*
gt
,
Context
*
ctx
);
Type
*
canonicalize
(
Context
*
ctx
,
int
ctx_depth
);
#ifndef PRODUCT
void
reify_signature
(
stringStream
*
ss
,
Context
*
ctx
);
void
print_on
(
outputStream
*
str
)
const
;
#endif
};
class
ArrayType
:
public
Type
{
private:
Type
*
_base
;
ArrayType
(
Type
*
base
)
:
_base
(
base
)
{}
public:
ArrayType
*
as_array
()
{
return
this
;
}
static
ArrayType
*
parse_generic_signature
(
DescriptorStream
*
str
);
bool
covariant_match
(
Type
*
gt
,
Context
*
ctx
);
ArrayType
*
canonicalize
(
Context
*
ctx
,
int
ctx_depth
);
void
bind_variables_to_parameters
(
Descriptor
*
sig
);
#ifndef PRODUCT
void
reify_signature
(
stringStream
*
ss
,
Context
*
ctx
);
void
print_on
(
outputStream
*
str
)
const
;
#endif
};
class
PrimitiveType
:
public
Type
{
friend
class
Type
;
private:
char
_type
;
// includes V for void
PrimitiveType
(
char
&
type
)
:
_type
(
type
)
{}
public:
PrimitiveType
*
as_primitive
()
{
return
this
;
}
bool
covariant_match
(
Type
*
gt
,
Context
*
ctx
);
PrimitiveType
*
canonicalize
(
Context
*
ctx
,
int
ctx_depth
);
void
bind_variables_to_parameters
(
Descriptor
*
sig
);
#ifndef PRODUCT
void
reify_signature
(
stringStream
*
ss
,
Context
*
ctx
);
void
print_on
(
outputStream
*
str
)
const
;
#endif
};
class
TypeArgument
:
public
ResourceObj
{
private:
Type
*
_lower_bound
;
Type
*
_upper_bound
;
// may be null or == _lower_bound
TypeArgument
(
Type
*
lower_bound
,
Type
*
upper_bound
)
:
_lower_bound
(
lower_bound
),
_upper_bound
(
upper_bound
)
{}
public:
static
TypeArgument
*
parse_generic_signature
(
DescriptorStream
*
str
);
Type
*
lower_bound
()
{
return
_lower_bound
;
}
Type
*
upper_bound
()
{
return
_upper_bound
;
}
void
bind_variables_to_parameters
(
Descriptor
*
sig
);
TypeArgument
*
canonicalize
(
Context
*
ctx
,
int
ctx_depth
);
bool
covariant_match
(
TypeArgument
*
a
,
Context
*
ctx
);
#ifndef PRODUCT
void
print_on
(
outputStream
*
str
)
const
;
#endif
};
class
Context
:
public
ResourceObj
{
private:
DescriptorCache
*
_cache
;
GrowableArray
<
ClassType
*>
_type_arguments
;
void
reset_to_mark
(
int
size
);
public:
// When this object goes out of scope or 'destroy' is
// called, then the application of the type to the
// context is wound-back (unless it's been deactivated).
class
Mark
:
public
StackObj
{
private:
mutable
Context
*
_context
;
int
_marked_size
;
bool
is_active
()
const
{
return
_context
!=
NULL
;
}
void
deactivate
()
const
{
_context
=
NULL
;
}
public:
Mark
()
:
_context
(
NULL
),
_marked_size
(
0
)
{}
Mark
(
Context
*
ctx
,
int
sz
)
:
_context
(
ctx
),
_marked_size
(
sz
)
{}
Mark
(
const
Mark
&
m
)
:
_context
(
m
.
_context
),
_marked_size
(
m
.
_marked_size
)
{
m
.
deactivate
();
// Ownership is transferred
}
Mark
&
operator
=
(
const
Mark
&
cm
)
{
destroy
();
_context
=
cm
.
_context
;
_marked_size
=
cm
.
_marked_size
;
cm
.
deactivate
();
return
*
this
;
}
void
destroy
();
~
Mark
()
{
destroy
();
}
};
Context
(
DescriptorCache
*
cache
)
:
_cache
(
cache
)
{}
Mark
mark
()
{
return
Mark
(
this
,
_type_arguments
.
length
());
}
void
apply_type_arguments
(
InstanceKlass
*
current
,
InstanceKlass
*
super
,
TRAPS
);
ClassType
*
at_depth
(
int
i
)
const
;
#ifndef PRODUCT
void
print_on
(
outputStream
*
str
)
const
;
#endif
};
/**
* Contains a cache of descriptors for classes and methods so they can be
* looked-up instead of reparsing each time they are needed.
*/
class
DescriptorCache
:
public
ResourceObj
{
private:
ResourceHashtable
<
InstanceKlass
*
,
ClassDescriptor
*>
_class_descriptors
;
ResourceHashtable
<
Method
*
,
MethodDescriptor
*>
_method_descriptors
;
public:
ClassDescriptor
*
descriptor_for
(
InstanceKlass
*
ikh
,
TRAPS
);
MethodDescriptor
*
descriptor_for
(
Method
*
mh
,
ClassDescriptor
*
cd
,
TRAPS
);
// Class descriptor derived from method holder
MethodDescriptor
*
descriptor_for
(
Method
*
mh
,
TRAPS
);
};
}
// namespace generic
#endif // SHARE_VM_CLASSFILE_GENERICSIGNATURES_HPP
src/share/vm/runtime/globals.hpp
浏览文件 @
2182157d
...
...
@@ -3682,15 +3682,9 @@ class CommandLineFlags {
develop(bool, TraceDefaultMethods, false, \
"Trace the default method processing steps") \
\
develop(bool, ParseAllGenericSignatures, false, \
"Parse all generic signatures while classloading") \
\
develop(bool, VerifyGenericSignatures, false, \
"Abort VM on erroneous or inconsistent generic signatures") \
\
product(bool, ParseGenericDefaults, false, \
"Parse generic signatures for default method handling") \
\
product(bool, UseVMInterruptibleIO, false, \
"(Unstable, Solaris-specific) Thread interrupt before or with " \
"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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录