Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
50f0f018
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看板
提交
50f0f018
编写于
6月 23, 2011
作者:
J
jrose
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
7056328: JSR 292 invocation sometimes fails in adapters for types not on boot class path
Reviewed-by: never
上级
11d5fcaf
变更
26
隐藏空白更改
内联
并排
Showing
26 changed file
with
512 addition
and
58 deletion
+512
-58
src/cpu/sparc/vm/templateTable_sparc.cpp
src/cpu/sparc/vm/templateTable_sparc.cpp
+4
-1
src/cpu/x86/vm/templateTable_x86_32.cpp
src/cpu/x86/vm/templateTable_x86_32.cpp
+5
-3
src/cpu/x86/vm/templateTable_x86_64.cpp
src/cpu/x86/vm/templateTable_x86_64.cpp
+2
-0
src/share/vm/ci/ciEnv.cpp
src/share/vm/ci/ciEnv.cpp
+49
-5
src/share/vm/ci/ciEnv.hpp
src/share/vm/ci/ciEnv.hpp
+1
-0
src/share/vm/ci/ciField.cpp
src/share/vm/ci/ciField.cpp
+1
-1
src/share/vm/ci/ciMethod.cpp
src/share/vm/ci/ciMethod.cpp
+3
-2
src/share/vm/ci/ciMethodHandle.cpp
src/share/vm/ci/ciMethodHandle.cpp
+11
-1
src/share/vm/ci/ciObjArrayKlass.cpp
src/share/vm/ci/ciObjArrayKlass.cpp
+1
-0
src/share/vm/ci/ciSignature.cpp
src/share/vm/ci/ciSignature.cpp
+2
-2
src/share/vm/ci/ciSignature.hpp
src/share/vm/ci/ciSignature.hpp
+1
-1
src/share/vm/classfile/javaClasses.cpp
src/share/vm/classfile/javaClasses.cpp
+12
-0
src/share/vm/classfile/javaClasses.hpp
src/share/vm/classfile/javaClasses.hpp
+2
-0
src/share/vm/classfile/systemDictionary.cpp
src/share/vm/classfile/systemDictionary.cpp
+2
-0
src/share/vm/interpreter/linkResolver.cpp
src/share/vm/interpreter/linkResolver.cpp
+10
-0
src/share/vm/oops/constantPoolKlass.cpp
src/share/vm/oops/constantPoolKlass.cpp
+10
-1
src/share/vm/oops/constantPoolOop.cpp
src/share/vm/oops/constantPoolOop.cpp
+23
-0
src/share/vm/oops/constantPoolOop.hpp
src/share/vm/oops/constantPoolOop.hpp
+6
-1
src/share/vm/oops/cpCacheOop.cpp
src/share/vm/oops/cpCacheOop.cpp
+44
-0
src/share/vm/oops/cpCacheOop.hpp
src/share/vm/oops/cpCacheOop.hpp
+2
-0
src/share/vm/oops/methodOop.cpp
src/share/vm/oops/methodOop.cpp
+35
-1
src/share/vm/oops/methodOop.hpp
src/share/vm/oops/methodOop.hpp
+1
-0
src/share/vm/prims/methodHandleWalk.cpp
src/share/vm/prims/methodHandleWalk.cpp
+180
-29
src/share/vm/prims/methodHandleWalk.hpp
src/share/vm/prims/methodHandleWalk.hpp
+33
-8
src/share/vm/prims/methodHandles.cpp
src/share/vm/prims/methodHandles.cpp
+70
-2
src/share/vm/prims/methodHandles.hpp
src/share/vm/prims/methodHandles.hpp
+2
-0
未找到文件。
src/cpu/sparc/vm/templateTable_sparc.cpp
浏览文件 @
50f0f018
...
...
@@ -266,7 +266,7 @@ void TemplateTable::sipush() {
void
TemplateTable
::
ldc
(
bool
wide
)
{
transition
(
vtos
,
vtos
);
Label
call_ldc
,
notInt
,
notString
,
notClass
,
exit
;
Label
call_ldc
,
notInt
,
isString
,
notString
,
notClass
,
exit
;
if
(
wide
)
{
__
get_2_byte_integer_at_bcp
(
1
,
G3_scratch
,
O1
,
InterpreterMacroAssembler
::
Unsigned
);
...
...
@@ -317,8 +317,11 @@ void TemplateTable::ldc(bool wide) {
__
bind
(
notInt
);
// __ cmp(O2, JVM_CONSTANT_String);
__
brx
(
Assembler
::
equal
,
true
,
Assembler
::
pt
,
isString
);
__
delayed
()
->
cmp
(
O2
,
JVM_CONSTANT_Object
);
__
brx
(
Assembler
::
notEqual
,
true
,
Assembler
::
pt
,
notString
);
__
delayed
()
->
ldf
(
FloatRegisterImpl
::
S
,
O0
,
O1
,
Ftos_f
);
__
bind
(
isString
);
__
ld_ptr
(
O0
,
O1
,
Otos_i
);
__
verify_oop
(
Otos_i
);
__
push
(
atos
);
...
...
src/cpu/x86/vm/templateTable_x86_32.cpp
浏览文件 @
50f0f018
...
...
@@ -373,15 +373,17 @@ void TemplateTable::ldc(bool wide) {
__
jcc
(
Assembler
::
equal
,
L
);
__
cmpl
(
rdx
,
JVM_CONSTANT_String
);
__
jcc
(
Assembler
::
equal
,
L
);
__
cmpl
(
rdx
,
JVM_CONSTANT_Object
);
__
jcc
(
Assembler
::
equal
,
L
);
__
stop
(
"unexpected tag type in ldc"
);
__
bind
(
L
);
}
#endif
Label
isOop
;
// atos and itos
//
String is only
oop type we will see here
__
cmpl
(
rdx
,
JVM_CONSTANT_
String
);
__
jccb
(
Assembler
::
e
qual
,
isOop
);
//
Integer is only non-
oop type we will see here
__
cmpl
(
rdx
,
JVM_CONSTANT_
Integer
);
__
jccb
(
Assembler
::
notE
qual
,
isOop
);
__
movl
(
rax
,
Address
(
rcx
,
rbx
,
Address
::
times_ptr
,
base_offset
));
__
push
(
itos
);
__
jmp
(
Done
);
...
...
src/cpu/x86/vm/templateTable_x86_64.cpp
浏览文件 @
50f0f018
...
...
@@ -385,6 +385,8 @@ void TemplateTable::ldc(bool wide) {
__
jcc
(
Assembler
::
equal
,
L
);
__
cmpl
(
rdx
,
JVM_CONSTANT_String
);
__
jcc
(
Assembler
::
equal
,
L
);
__
cmpl
(
rdx
,
JVM_CONSTANT_Object
);
__
jcc
(
Assembler
::
equal
,
L
);
__
stop
(
"unexpected tag type in ldc"
);
__
bind
(
L
);
}
...
...
src/share/vm/ci/ciEnv.cpp
浏览文件 @
50f0f018
...
...
@@ -50,6 +50,7 @@
#include "oops/oop.inline.hpp"
#include "oops/oop.inline2.hpp"
#include "prims/jvmtiExport.hpp"
#include "prims/methodHandleWalk.hpp"
#include "runtime/init.hpp"
#include "runtime/reflection.hpp"
#include "runtime/sharedRuntime.hpp"
...
...
@@ -371,6 +372,7 @@ bool ciEnv::check_klass_accessibility(ciKlass* accessing_klass,
// ------------------------------------------------------------------
// ciEnv::get_klass_by_name_impl
ciKlass
*
ciEnv
::
get_klass_by_name_impl
(
ciKlass
*
accessing_klass
,
constantPoolHandle
cpool
,
ciSymbol
*
name
,
bool
require_local
)
{
ASSERT_IN_VM
;
...
...
@@ -386,7 +388,7 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass,
sym
->
utf8_length
()
-
2
,
KILL_COMPILE_ON_FATAL_
(
_unloaded_ciinstance_klass
));
ciSymbol
*
strippedname
=
get_symbol
(
strippedsym
);
return
get_klass_by_name_impl
(
accessing_klass
,
strippedname
,
require_local
);
return
get_klass_by_name_impl
(
accessing_klass
,
cpool
,
strippedname
,
require_local
);
}
// Check for prior unloaded klass. The SystemDictionary's answers
...
...
@@ -443,6 +445,7 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass,
// Get element ciKlass recursively.
ciKlass
*
elem_klass
=
get_klass_by_name_impl
(
accessing_klass
,
cpool
,
get_symbol
(
elem_sym
),
require_local
);
if
(
elem_klass
!=
NULL
&&
elem_klass
->
is_loaded
())
{
...
...
@@ -451,6 +454,19 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass,
}
}
if
(
found_klass
()
==
NULL
&&
!
cpool
.
is_null
()
&&
cpool
->
has_preresolution
())
{
// Look inside the constant pool for pre-resolved class entries.
for
(
int
i
=
cpool
->
length
()
-
1
;
i
>=
1
;
i
--
)
{
if
(
cpool
->
tag_at
(
i
).
is_klass
())
{
klassOop
kls
=
cpool
->
resolved_klass_at
(
i
);
if
(
Klass
::
cast
(
kls
)
->
name
()
==
sym
)
{
found_klass
=
KlassHandle
(
THREAD
,
kls
);
break
;
}
}
}
}
if
(
found_klass
()
!=
NULL
)
{
// Found it. Build a CI handle.
return
get_object
(
found_klass
())
->
as_klass
();
...
...
@@ -468,6 +484,7 @@ ciKlass* ciEnv::get_klass_by_name(ciKlass* accessing_klass,
ciSymbol
*
klass_name
,
bool
require_local
)
{
GUARDED_VM_ENTRY
(
return
get_klass_by_name_impl
(
accessing_klass
,
constantPoolHandle
(),
klass_name
,
require_local
);)
}
...
...
@@ -508,13 +525,14 @@ ciKlass* ciEnv::get_klass_by_index_impl(constantPoolHandle cpool,
if
(
klass
.
is_null
())
{
// Not found in constant pool. Use the name to do the lookup.
ciKlass
*
k
=
get_klass_by_name_impl
(
accessor
,
cpool
,
get_symbol
(
klass_name
),
false
);
// Calculate accessibility the hard way.
if
(
!
k
->
is_loaded
())
{
is_accessible
=
false
;
}
else
if
(
k
->
loader
()
!=
accessor
->
loader
()
&&
get_klass_by_name_impl
(
accessor
,
k
->
name
(),
true
)
==
NULL
)
{
get_klass_by_name_impl
(
accessor
,
cpool
,
k
->
name
(),
true
)
==
NULL
)
{
// Loaded only remotely. Not linked yet.
is_accessible
=
false
;
}
else
{
...
...
@@ -565,7 +583,7 @@ ciConstant ciEnv::get_constant_by_index_impl(constantPoolHandle cpool,
index
=
cpc_entry
->
constant_pool_index
();
oop
obj
=
cpc_entry
->
f1
();
if
(
obj
!=
NULL
)
{
assert
(
obj
->
is_instance
()
,
"must be an insta
nce"
);
assert
(
obj
->
is_instance
()
||
obj
->
is_array
(),
"must be a Java refere
nce"
);
ciObject
*
ciobj
=
get_object
(
obj
);
return
ciConstant
(
T_OBJECT
,
ciobj
);
}
...
...
@@ -607,7 +625,7 @@ ciConstant ciEnv::get_constant_by_index_impl(constantPoolHandle cpool,
return
ciConstant
(
T_OBJECT
,
klass
->
java_mirror
());
}
else
if
(
tag
.
is_object
())
{
oop
obj
=
cpool
->
object_at
(
index
);
assert
(
obj
->
is_instance
()
,
"must be an insta
nce"
);
assert
(
obj
->
is_instance
()
||
obj
->
is_array
(),
"must be a Java refere
nce"
);
ciObject
*
ciobj
=
get_object
(
obj
);
return
ciConstant
(
T_OBJECT
,
ciobj
);
}
else
if
(
tag
.
is_method_type
())
{
...
...
@@ -729,9 +747,35 @@ ciMethod* ciEnv::get_method_by_index_impl(constantPoolHandle cpool,
Symbol
*
name_sym
=
cpool
->
name_ref_at
(
index
);
Symbol
*
sig_sym
=
cpool
->
signature_ref_at
(
index
);
if
(
cpool
->
has_preresolution
()
||
(
holder
==
ciEnv
::
MethodHandle_klass
()
&&
methodOopDesc
::
is_method_handle_invoke_name
(
name_sym
)))
{
// Short-circuit lookups for JSR 292-related call sites.
// That is, do not rely only on name-based lookups, because they may fail
// if the names are not resolvable in the boot class loader (7056328).
switch
(
bc
)
{
case
Bytecodes
::
_invokevirtual
:
case
Bytecodes
::
_invokeinterface
:
case
Bytecodes
::
_invokespecial
:
case
Bytecodes
::
_invokestatic
:
{
methodOop
m
=
constantPoolOopDesc
::
method_at_if_loaded
(
cpool
,
index
,
bc
);
if
(
m
!=
NULL
)
{
return
get_object
(
m
)
->
as_method
();
}
}
}
}
if
(
holder_is_accessible
)
{
// Our declared holder is loaded.
instanceKlass
*
lookup
=
declared_holder
->
get_instanceKlass
();
methodOop
m
=
lookup_method
(
accessor
->
get_instanceKlass
(),
lookup
,
name_sym
,
sig_sym
,
bc
);
if
(
m
!=
NULL
&&
(
bc
==
Bytecodes
::
_invokestatic
?
instanceKlass
::
cast
(
m
->
method_holder
())
->
is_not_initialized
()
:
!
instanceKlass
::
cast
(
m
->
method_holder
())
->
is_loaded
()))
{
m
=
NULL
;
}
if
(
m
!=
NULL
)
{
// We found the method.
return
get_object
(
m
)
->
as_method
();
...
...
@@ -1046,7 +1090,7 @@ void ciEnv::register_method(ciMethod* target,
// ciEnv::find_system_klass
ciKlass
*
ciEnv
::
find_system_klass
(
ciSymbol
*
klass_name
)
{
VM_ENTRY_MARK
;
return
get_klass_by_name_impl
(
NULL
,
klass_name
,
false
);
return
get_klass_by_name_impl
(
NULL
,
constantPoolHandle
(),
klass_name
,
false
);
}
// ------------------------------------------------------------------
...
...
src/share/vm/ci/ciEnv.hpp
浏览文件 @
50f0f018
...
...
@@ -137,6 +137,7 @@ private:
// Implementation methods for loading and constant pool access.
ciKlass
*
get_klass_by_name_impl
(
ciKlass
*
accessing_klass
,
constantPoolHandle
cpool
,
ciSymbol
*
klass_name
,
bool
require_local
);
ciKlass
*
get_klass_by_index_impl
(
constantPoolHandle
cpool
,
...
...
src/share/vm/ci/ciField.cpp
浏览文件 @
50f0f018
...
...
@@ -287,7 +287,7 @@ ciType* ciField::compute_type() {
}
ciType
*
ciField
::
compute_type_impl
()
{
ciKlass
*
type
=
CURRENT_ENV
->
get_klass_by_name_impl
(
_holder
,
_signature
,
false
);
ciKlass
*
type
=
CURRENT_ENV
->
get_klass_by_name_impl
(
_holder
,
constantPoolHandle
(),
_signature
,
false
);
if
(
!
type
->
is_primitive_type
()
&&
is_shared
())
{
// We must not cache a pointer to an unshared type, in a shared field.
bool
type_is_also_shared
=
false
;
...
...
src/share/vm/ci/ciMethod.cpp
浏览文件 @
50f0f018
...
...
@@ -125,7 +125,8 @@ ciMethod::ciMethod(methodHandle h_m) : ciObject(h_m) {
_name
=
env
->
get_symbol
(
h_m
()
->
name
());
_holder
=
env
->
get_object
(
h_m
()
->
method_holder
())
->
as_instance_klass
();
ciSymbol
*
sig_symbol
=
env
->
get_symbol
(
h_m
()
->
signature
());
_signature
=
new
(
env
->
arena
())
ciSignature
(
_holder
,
sig_symbol
);
constantPoolHandle
cpool
=
h_m
()
->
constants
();
_signature
=
new
(
env
->
arena
())
ciSignature
(
_holder
,
cpool
,
sig_symbol
);
_method_data
=
NULL
;
// Take a snapshot of these values, so they will be commensurate with the MDO.
if
(
ProfileInterpreter
||
TieredCompilation
)
{
...
...
@@ -152,7 +153,7 @@ ciMethod::ciMethod(ciInstanceKlass* holder,
// These fields are always filled in.
_name
=
name
;
_holder
=
holder
;
_signature
=
new
(
CURRENT_ENV
->
arena
())
ciSignature
(
_holder
,
signature
);
_signature
=
new
(
CURRENT_ENV
->
arena
())
ciSignature
(
_holder
,
constantPoolHandle
(),
signature
);
_intrinsic_id
=
vmIntrinsics
::
_none
;
_liveness
=
NULL
;
_can_be_statically_bound
=
false
;
...
...
src/share/vm/ci/ciMethodHandle.cpp
浏览文件 @
50f0f018
...
...
@@ -41,6 +41,16 @@ ciMethod* ciMethodHandle::get_adapter_impl(bool is_invokedynamic) const {
VM_ENTRY_MARK
;
Handle
h
(
get_oop
());
methodHandle
callee
(
_callee
->
get_methodOop
());
assert
(
callee
->
is_method_handle_invoke
(),
""
);
oop
mt1
=
callee
->
method_handle_type
();
oop
mt2
=
java_lang_invoke_MethodHandle
::
type
(
h
());
if
(
!
java_lang_invoke_MethodType
::
equals
(
mt1
,
mt2
))
{
if
(
PrintMiscellaneous
&&
(
Verbose
||
WizardMode
))
{
tty
->
print_cr
(
"ciMethodHandle::get_adapter: types not equal"
);
mt1
->
print
();
mt2
->
print
();
}
return
NULL
;
}
// We catch all exceptions here that could happen in the method
// handle compiler and stop the VM.
MethodHandleCompiler
mhc
(
h
,
callee
->
name
(),
callee
->
signature
(),
_profile
.
count
(),
is_invokedynamic
,
THREAD
);
...
...
@@ -53,7 +63,7 @@ ciMethod* ciMethodHandle::get_adapter_impl(bool is_invokedynamic) const {
if
(
PrintMiscellaneous
&&
(
Verbose
||
WizardMode
))
{
tty
->
print
(
"*** ciMethodHandle::get_adapter => "
);
PENDING_EXCEPTION
->
print
();
tty
->
print
(
"*** get_adapter (%s): "
,
is_invokedynamic
?
"indy"
:
"mh"
);
((
ciObject
*
)
this
)
->
print
();
//@@
tty
->
print
(
"*** get_adapter (%s): "
,
is_invokedynamic
?
"indy"
:
"mh"
);
((
ciObject
*
)
this
)
->
print
();
}
CLEAR_PENDING_EXCEPTION
;
return
NULL
;
...
...
src/share/vm/ci/ciObjArrayKlass.cpp
浏览文件 @
50f0f018
...
...
@@ -93,6 +93,7 @@ ciKlass* ciObjArrayKlass::element_klass() {
// element klass by name.
_element_klass
=
CURRENT_THREAD_ENV
->
get_klass_by_name_impl
(
this
,
constantPoolHandle
(),
construct_array_name
(
base_element_klass
()
->
name
(),
dimension
()
-
1
),
false
);
...
...
src/share/vm/ci/ciSignature.cpp
浏览文件 @
50f0f018
...
...
@@ -35,7 +35,7 @@
// ------------------------------------------------------------------
// ciSignature::ciSignature
ciSignature
::
ciSignature
(
ciKlass
*
accessing_klass
,
ciSymbol
*
symbol
)
{
ciSignature
::
ciSignature
(
ciKlass
*
accessing_klass
,
c
onstantPoolHandle
cpool
,
c
iSymbol
*
symbol
)
{
ASSERT_IN_VM
;
EXCEPTION_CONTEXT
;
_accessing_klass
=
accessing_klass
;
...
...
@@ -64,7 +64,7 @@ ciSignature::ciSignature(ciKlass* accessing_klass, ciSymbol* symbol) {
CLEAR_PENDING_EXCEPTION
;
}
else
{
ciSymbol
*
klass_name
=
env
->
get_symbol
(
name
);
type
=
env
->
get_klass_by_name_impl
(
_accessing_klass
,
klass_name
,
false
);
type
=
env
->
get_klass_by_name_impl
(
_accessing_klass
,
cpool
,
klass_name
,
false
);
}
}
_types
->
append
(
type
);
...
...
src/share/vm/ci/ciSignature.hpp
浏览文件 @
50f0f018
...
...
@@ -44,7 +44,7 @@ private:
friend
class
ciMethod
;
ciSignature
(
ciKlass
*
accessing_klass
,
ciSymbol
*
signature
);
ciSignature
(
ciKlass
*
accessing_klass
,
c
onstantPoolHandle
cpool
,
c
iSymbol
*
signature
);
void
get_all_klasses
();
...
...
src/share/vm/classfile/javaClasses.cpp
浏览文件 @
50f0f018
...
...
@@ -2574,6 +2574,18 @@ Symbol* java_lang_invoke_MethodType::as_signature(oop mt, bool intern_if_not_fou
return
name
;
}
bool
java_lang_invoke_MethodType
::
equals
(
oop
mt1
,
oop
mt2
)
{
if
(
rtype
(
mt1
)
!=
rtype
(
mt2
))
return
false
;
if
(
ptype_count
(
mt1
)
!=
ptype_count
(
mt2
))
return
false
;
for
(
int
i
=
ptype_count
(
mt1
)
-
1
;
i
>=
0
;
i
--
)
{
if
(
ptype
(
mt1
,
i
)
!=
ptype
(
mt2
,
i
))
return
false
;
}
return
true
;
}
oop
java_lang_invoke_MethodType
::
rtype
(
oop
mt
)
{
assert
(
is_instance
(
mt
),
"must be a MethodType"
);
return
mt
->
obj_field
(
_rtype_offset
);
...
...
src/share/vm/classfile/javaClasses.hpp
浏览文件 @
50f0f018
...
...
@@ -1079,6 +1079,8 @@ class java_lang_invoke_MethodType: AllStatic {
return
obj
!=
NULL
&&
obj
->
klass
()
==
SystemDictionary
::
MethodType_klass
();
}
static
bool
equals
(
oop
mt1
,
oop
mt2
);
// Accessors for code generation:
static
int
rtype_offset_in_bytes
()
{
return
_rtype_offset
;
}
static
int
ptypes_offset_in_bytes
()
{
return
_ptypes_offset
;
}
...
...
src/share/vm/classfile/systemDictionary.cpp
浏览文件 @
50f0f018
...
...
@@ -2367,6 +2367,8 @@ methodOop SystemDictionary::find_method_handle_invoke(Symbol* name,
// Link m to his method type, if it is suitably generic.
oop
mtform
=
java_lang_invoke_MethodType
::
form
(
mt
());
if
(
mtform
!=
NULL
&&
mt
()
==
java_lang_invoke_MethodTypeForm
::
erasedType
(
mtform
)
// vmlayout must be an invokeExact:
&&
name_id
==
vmSymbols
::
VM_SYMBOL_ENUM_NAME
(
invokeExact_name
)
&&
java_lang_invoke_MethodTypeForm
::
vmlayout_offset_in_bytes
()
>
0
)
{
java_lang_invoke_MethodTypeForm
::
init_vmlayout
(
mtform
,
m
());
}
...
...
src/share/vm/interpreter/linkResolver.cpp
浏览文件 @
50f0f018
...
...
@@ -294,6 +294,16 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle& re
Symbol
*
method_signature
=
pool
->
signature_ref_at
(
index
);
KlassHandle
current_klass
(
THREAD
,
pool
->
pool_holder
());
if
(
pool
->
has_preresolution
()
||
(
resolved_klass
()
==
SystemDictionary
::
MethodHandle_klass
()
&&
methodOopDesc
::
is_method_handle_invoke_name
(
method_name
)))
{
methodOop
result_oop
=
constantPoolOopDesc
::
method_at_if_loaded
(
pool
,
index
);
if
(
result_oop
!=
NULL
)
{
resolved_method
=
methodHandle
(
THREAD
,
result_oop
);
return
;
}
}
resolve_method
(
resolved_method
,
resolved_klass
,
method_name
,
method_signature
,
current_klass
,
true
,
CHECK
);
}
...
...
src/share/vm/oops/constantPoolKlass.cpp
浏览文件 @
50f0f018
...
...
@@ -310,10 +310,14 @@ void constantPoolKlass::oop_print_on(oop obj, outputStream* st) {
st
->
print
(
" - flags: 0x%x"
,
cp
->
flags
());
if
(
cp
->
has_pseudo_string
())
st
->
print
(
" has_pseudo_string"
);
if
(
cp
->
has_invokedynamic
())
st
->
print
(
" has_invokedynamic"
);
if
(
cp
->
has_preresolution
())
st
->
print
(
" has_preresolution"
);
st
->
cr
();
}
if
(
cp
->
pool_holder
()
!=
NULL
)
{
bool
extra
=
(
instanceKlass
::
cast
(
cp
->
pool_holder
())
->
constants
()
!=
cp
);
st
->
print_cr
(
" - holder: "
INTPTR_FORMAT
"%s"
,
cp
->
pool_holder
(),
(
extra
?
" (extra)"
:
""
));
}
st
->
print_cr
(
" - cache: "
INTPTR_FORMAT
,
cp
->
cache
());
for
(
int
index
=
1
;
index
<
cp
->
length
();
index
++
)
{
// Index 0 is unused
st
->
print
(
" - %3d : "
,
index
);
cp
->
tag_at
(
index
).
print_on
(
st
);
...
...
@@ -414,10 +418,15 @@ void constantPoolKlass::oop_print_value_on(oop obj, outputStream* st) {
st
->
print
(
"constant pool [%d]"
,
cp
->
length
());
if
(
cp
->
has_pseudo_string
())
st
->
print
(
"/pseudo_string"
);
if
(
cp
->
has_invokedynamic
())
st
->
print
(
"/invokedynamic"
);
if
(
cp
->
has_preresolution
())
st
->
print
(
"/preresolution"
);
if
(
cp
->
operands
()
!=
NULL
)
st
->
print
(
"/operands[%d]"
,
cp
->
operands
()
->
length
());
cp
->
print_address_on
(
st
);
st
->
print
(
" for "
);
cp
->
pool_holder
()
->
print_value_on
(
st
);
if
(
cp
->
pool_holder
()
!=
NULL
)
{
bool
extra
=
(
instanceKlass
::
cast
(
cp
->
pool_holder
())
->
constants
()
!=
cp
);
if
(
extra
)
st
->
print
(
" (extra)"
);
}
if
(
cp
->
cache
()
!=
NULL
)
{
st
->
print
(
" cache="
PTR_FORMAT
,
cp
->
cache
());
}
...
...
src/share/vm/oops/constantPoolOop.cpp
浏览文件 @
50f0f018
...
...
@@ -266,6 +266,29 @@ klassOop constantPoolOopDesc::klass_ref_at_if_loaded_check(constantPoolHandle th
}
methodOop
constantPoolOopDesc
::
method_at_if_loaded
(
constantPoolHandle
cpool
,
int
which
,
Bytecodes
::
Code
invoke_code
)
{
assert
(
!
constantPoolCacheOopDesc
::
is_secondary_index
(
which
),
"no indy instruction here"
);
if
(
cpool
->
cache
()
==
NULL
)
return
false
;
// nothing to load yet
int
cache_index
=
which
-
CPCACHE_INDEX_TAG
;
if
(
!
(
cache_index
>=
0
&&
cache_index
<
cpool
->
cache
()
->
length
()))
{
if
(
PrintMiscellaneous
&&
(
Verbose
||
WizardMode
))
{
tty
->
print_cr
(
"bad operand %d for %d in:"
,
which
,
invoke_code
);
cpool
->
print
();
}
return
NULL
;
}
ConstantPoolCacheEntry
*
e
=
cpool
->
cache
()
->
entry_at
(
cache_index
);
if
(
invoke_code
!=
Bytecodes
::
_illegal
)
return
e
->
get_method_if_resolved
(
invoke_code
,
cpool
);
Bytecodes
::
Code
bc
;
if
((
bc
=
e
->
bytecode_1
())
!=
(
Bytecodes
::
Code
)
0
)
return
e
->
get_method_if_resolved
(
bc
,
cpool
);
if
((
bc
=
e
->
bytecode_2
())
!=
(
Bytecodes
::
Code
)
0
)
return
e
->
get_method_if_resolved
(
bc
,
cpool
);
return
NULL
;
}
Symbol
*
constantPoolOopDesc
::
impl_name_ref_at
(
int
which
,
bool
uncached
)
{
int
name_index
=
name_ref_index_at
(
impl_name_and_type_ref_index_at
(
which
,
uncached
));
return
symbol_at
(
name_index
);
...
...
src/share/vm/oops/constantPoolOop.hpp
浏览文件 @
50f0f018
...
...
@@ -103,7 +103,8 @@ class constantPoolOopDesc : public oopDesc {
enum
FlagBit
{
FB_has_invokedynamic
=
1
,
FB_has_pseudo_string
=
2
FB_has_pseudo_string
=
2
,
FB_has_preresolution
=
3
};
int
flags
()
const
{
return
_flags
;
}
...
...
@@ -179,8 +180,10 @@ class constantPoolOopDesc : public oopDesc {
bool
has_pseudo_string
()
const
{
return
flag_at
(
FB_has_pseudo_string
);
}
bool
has_invokedynamic
()
const
{
return
flag_at
(
FB_has_invokedynamic
);
}
bool
has_preresolution
()
const
{
return
flag_at
(
FB_has_preresolution
);
}
void
set_pseudo_string
()
{
set_flag_at
(
FB_has_pseudo_string
);
}
void
set_invokedynamic
()
{
set_flag_at
(
FB_has_invokedynamic
);
}
void
set_preresolution
()
{
set_flag_at
(
FB_has_preresolution
);
}
// Klass holding pool
klassOop
pool_holder
()
const
{
return
_pool_holder
;
}
...
...
@@ -663,6 +666,8 @@ class constantPoolOopDesc : public oopDesc {
friend
class
SystemDictionary
;
// Used by compiler to prevent classloading.
static
methodOop
method_at_if_loaded
(
constantPoolHandle
this_oop
,
int
which
,
Bytecodes
::
Code
bc
=
Bytecodes
::
_illegal
);
static
klassOop
klass_at_if_loaded
(
constantPoolHandle
this_oop
,
int
which
);
static
klassOop
klass_ref_at_if_loaded
(
constantPoolHandle
this_oop
,
int
which
);
// Same as above - but does LinkResolving.
...
...
src/share/vm/oops/cpCacheOop.cpp
浏览文件 @
50f0f018
...
...
@@ -295,6 +295,50 @@ void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site, methodHandle sig
}
methodOop
ConstantPoolCacheEntry
::
get_method_if_resolved
(
Bytecodes
::
Code
invoke_code
,
constantPoolHandle
cpool
)
{
assert
(
invoke_code
>
(
Bytecodes
::
Code
)
0
,
"bad query"
);
if
(
is_secondary_entry
())
{
return
cpool
->
cache
()
->
entry_at
(
main_entry_index
())
->
get_method_if_resolved
(
invoke_code
,
cpool
);
}
// Decode the action of set_method and set_interface_call
if
(
bytecode_1
()
==
invoke_code
)
{
oop
f1
=
_f1
;
if
(
f1
!=
NULL
)
{
switch
(
invoke_code
)
{
case
Bytecodes
::
_invokeinterface
:
assert
(
f1
->
is_klass
(),
""
);
return
klassItable
::
method_for_itable_index
(
klassOop
(
f1
),
(
int
)
f2
());
case
Bytecodes
::
_invokestatic
:
case
Bytecodes
::
_invokespecial
:
assert
(
f1
->
is_method
(),
""
);
return
methodOop
(
f1
);
}
}
}
if
(
bytecode_2
()
==
invoke_code
)
{
switch
(
invoke_code
)
{
case
Bytecodes
::
_invokevirtual
:
if
(
is_vfinal
())
{
// invokevirtual
methodOop
m
=
methodOop
((
intptr_t
)
f2
());
assert
(
m
->
is_method
(),
""
);
return
m
;
}
else
{
int
holder_index
=
cpool
->
uncached_klass_ref_index_at
(
constant_pool_index
());
if
(
cpool
->
tag_at
(
holder_index
).
is_klass
())
{
klassOop
klass
=
cpool
->
resolved_klass_at
(
holder_index
);
if
(
!
Klass
::
cast
(
klass
)
->
oop_is_instance
())
klass
=
SystemDictionary
::
Object_klass
();
return
instanceKlass
::
cast
(
klass
)
->
method_at_vtable
((
int
)
f2
());
}
}
}
}
return
NULL
;
}
class
LocalOopClosure
:
public
OopClosure
{
private:
void
(
*
_f
)(
oop
*
);
...
...
src/share/vm/oops/cpCacheOop.hpp
浏览文件 @
50f0f018
...
...
@@ -194,6 +194,8 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
methodHandle
signature_invoker
// determines signature information
);
methodOop
get_method_if_resolved
(
Bytecodes
::
Code
invoke_code
,
constantPoolHandle
cpool
);
// For JVM_CONSTANT_InvokeDynamic cache entries:
void
initialize_bootstrap_method_index_in_cache
(
int
bsm_cache_index
);
int
bootstrap_method_index_in_cache
();
...
...
src/share/vm/oops/methodOop.cpp
浏览文件 @
50f0f018
...
...
@@ -928,14 +928,40 @@ methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
name
->
increment_refcount
();
signature
->
increment_refcount
();
// record non-BCP method types in the constant pool
GrowableArray
<
KlassHandle
>*
extra_klasses
=
NULL
;
for
(
int
i
=
-
1
,
len
=
java_lang_invoke_MethodType
::
ptype_count
(
method_type
());
i
<
len
;
i
++
)
{
oop
ptype
=
(
i
==
-
1
?
java_lang_invoke_MethodType
::
rtype
(
method_type
())
:
java_lang_invoke_MethodType
::
ptype
(
method_type
(),
i
));
klassOop
klass
=
check_non_bcp_klass
(
java_lang_Class
::
as_klassOop
(
ptype
));
if
(
klass
!=
NULL
)
{
if
(
extra_klasses
==
NULL
)
extra_klasses
=
new
GrowableArray
<
KlassHandle
>
(
len
+
1
);
bool
dup
=
false
;
for
(
int
j
=
0
;
j
<
extra_klasses
->
length
();
j
++
)
{
if
(
extra_klasses
->
at
(
j
)
==
klass
)
{
dup
=
true
;
break
;
}
}
if
(
!
dup
)
extra_klasses
->
append
(
KlassHandle
(
THREAD
,
klass
));
}
}
int
extra_klass_count
=
(
extra_klasses
==
NULL
?
0
:
extra_klasses
->
length
());
int
cp_length
=
_imcp_limit
+
extra_klass_count
;
constantPoolHandle
cp
;
{
constantPoolOop
cp_oop
=
oopFactory
::
new_constantPool
(
_imcp_limit
,
IsSafeConc
,
CHECK_
(
empty
));
constantPoolOop
cp_oop
=
oopFactory
::
new_constantPool
(
cp_length
,
IsSafeConc
,
CHECK_
(
empty
));
cp
=
constantPoolHandle
(
THREAD
,
cp_oop
);
}
cp
->
symbol_at_put
(
_imcp_invoke_name
,
name
);
cp
->
symbol_at_put
(
_imcp_invoke_signature
,
signature
);
cp
->
string_at_put
(
_imcp_method_type_value
,
Universe
::
the_null_string
());
for
(
int
j
=
0
;
j
<
extra_klass_count
;
j
++
)
{
KlassHandle
klass
=
extra_klasses
->
at
(
j
);
cp
->
klass_at_put
(
_imcp_limit
+
j
,
klass
());
}
cp
->
set_preresolution
();
cp
->
set_pool_holder
(
holder
());
// set up the fancy stuff:
...
...
@@ -984,6 +1010,14 @@ methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
return
m
;
}
klassOop
methodOopDesc
::
check_non_bcp_klass
(
klassOop
klass
)
{
if
(
klass
!=
NULL
&&
Klass
::
cast
(
klass
)
->
class_loader
()
!=
NULL
)
{
if
(
Klass
::
cast
(
klass
)
->
oop_is_objArray
())
klass
=
objArrayKlass
::
cast
(
klass
)
->
bottom_klass
();
return
klass
;
}
return
NULL
;
}
methodHandle
methodOopDesc
::
clone_with_new_data
(
methodHandle
m
,
u_char
*
new_code
,
int
new_code_length
,
...
...
src/share/vm/oops/methodOop.hpp
浏览文件 @
50f0f018
...
...
@@ -600,6 +600,7 @@ class methodOopDesc : public oopDesc {
Symbol
*
signature
,
//anything at all
Handle
method_type
,
TRAPS
);
static
klassOop
check_non_bcp_klass
(
klassOop
klass
);
// these operate only on invoke methods:
oop
method_handle_type
()
const
;
static
jint
*
method_type_offsets_chain
();
// series of pointer-offsets, terminated by -1
...
...
src/share/vm/prims/methodHandleWalk.cpp
浏览文件 @
50f0f018
...
...
@@ -425,6 +425,8 @@ MethodHandleWalker::walk(TRAPS) {
ArgToken
arg
=
_outgoing
.
at
(
arg_slot
);
assert
(
dest
==
arg
.
basic_type
(),
""
);
arg
=
make_conversion
(
T_OBJECT
,
dest_klass
,
Bytecodes
::
_checkcast
,
arg
,
CHECK_
(
empty
));
// replace the object by the result of the cast, to make the compiler happy:
change_argument
(
T_OBJECT
,
arg_slot
,
T_OBJECT
,
arg
);
debug_only
(
dest_klass
=
(
klassOop
)
badOop
);
break
;
}
...
...
@@ -467,7 +469,7 @@ MethodHandleWalker::walk(TRAPS) {
ArgToken
arglist
[
2
];
arglist
[
0
]
=
arg
;
// outgoing 'this'
arglist
[
1
]
=
ArgToken
();
// sentinel
arg
=
make_invoke
(
NULL
,
unboxer
,
Bytecodes
::
_invokevirtual
,
false
,
1
,
&
arglist
[
0
],
CHECK_
(
empty
));
arg
=
make_invoke
(
methodHandle
()
,
unboxer
,
Bytecodes
::
_invokevirtual
,
false
,
1
,
&
arglist
[
0
],
CHECK_
(
empty
));
change_argument
(
T_OBJECT
,
arg_slot
,
dest
,
arg
);
break
;
}
...
...
@@ -483,7 +485,7 @@ MethodHandleWalker::walk(TRAPS) {
ArgToken
arglist
[
2
];
arglist
[
0
]
=
arg
;
// outgoing value
arglist
[
1
]
=
ArgToken
();
// sentinel
arg
=
make_invoke
(
NULL
,
boxer
,
Bytecodes
::
_invokestatic
,
false
,
1
,
&
arglist
[
0
],
CHECK_
(
empty
));
arg
=
make_invoke
(
methodHandle
()
,
boxer
,
Bytecodes
::
_invokestatic
,
false
,
1
,
&
arglist
[
0
],
CHECK_
(
empty
));
change_argument
(
src
,
arg_slot
,
T_OBJECT
,
arg
);
break
;
}
...
...
@@ -599,8 +601,9 @@ MethodHandleWalker::walk(TRAPS) {
lose
(
"bad vmlayout slot"
,
CHECK_
(
empty
));
}
// FIXME: consider inlining the invokee at the bytecode level
ArgToken
ret
=
make_invoke
(
method
Oop
(
invoker
),
vmIntrinsics
::
_none
,
ArgToken
ret
=
make_invoke
(
method
Handle
(
THREAD
,
methodOop
(
invoker
)),
vmIntrinsics
::
_invokeGeneric
,
Bytecodes
::
_invokevirtual
,
false
,
1
+
argc
,
&
arglist
[
0
],
CHECK_
(
empty
));
// The iid = _invokeGeneric really means to adjust reference types as needed.
DEBUG_ONLY
(
invoker
=
NULL
);
if
(
rtype
==
T_OBJECT
)
{
klassOop
rklass
=
java_lang_Class
::
as_klassOop
(
java_lang_invoke_MethodType
::
rtype
(
recursive_mtype
())
);
...
...
@@ -657,7 +660,7 @@ MethodHandleWalker::walk(TRAPS) {
arglist
[
0
]
=
array_arg
;
// value to check
arglist
[
1
]
=
length_arg
;
// length to check
arglist
[
2
]
=
ArgToken
();
// sentinel
make_invoke
(
NULL
,
vmIntrinsics
::
_checkSpreadArgument
,
make_invoke
(
methodHandle
()
,
vmIntrinsics
::
_checkSpreadArgument
,
Bytecodes
::
_invokestatic
,
false
,
2
,
&
arglist
[
0
],
CHECK_
(
empty
));
// Spread out the array elements.
...
...
@@ -680,7 +683,7 @@ MethodHandleWalker::walk(TRAPS) {
ArgToken
offset_arg
=
make_prim_constant
(
T_INT
,
&
offset_jvalue
,
CHECK_
(
empty
));
ArgToken
element_arg
=
make_fetch
(
element_type
,
element_klass
(),
aload_op
,
array_arg
,
offset_arg
,
CHECK_
(
empty
));
change_argument
(
T_VOID
,
ap
,
element_type
,
element_arg
);
ap
+=
type2size
[
element_type
];
//ap += type2size[element_type]; // don't do this; insert next arg to *right* of previous
}
break
;
}
...
...
@@ -731,7 +734,7 @@ MethodHandleWalker::walk(TRAPS) {
}
assert
(
ap
==
_outgoing_argc
,
""
);
arglist
[
ap
]
=
ArgToken
();
// add a sentinel, for the sake of asserts
return
make_invoke
(
chain
().
last_method
_oop
(),
return
make_invoke
(
chain
().
last_method
(),
vmIntrinsics
::
_none
,
chain
().
last_invoke_code
(),
true
,
ap
,
arglist
,
THREAD
);
...
...
@@ -853,7 +856,6 @@ void MethodHandleWalker::retype_raw_conversion(BasicType src, BasicType dst, boo
if
(
src
!=
dst
)
{
if
(
MethodHandles
::
same_basic_type_for_returns
(
src
,
dst
,
/*raw*/
true
))
{
if
(
MethodHandles
::
is_float_fixed_reinterpretation_cast
(
src
,
dst
))
{
if
(
for_return
)
Untested
(
"MHW return raw conversion"
);
// still untested
vmIntrinsics
::
ID
iid
=
vmIntrinsics
::
for_raw_conversion
(
src
,
dst
);
if
(
iid
==
vmIntrinsics
::
_none
)
{
lose
(
"no raw conversion method"
,
CHECK
);
...
...
@@ -865,18 +867,24 @@ void MethodHandleWalker::retype_raw_conversion(BasicType src, BasicType dst, boo
assert
(
arg
.
token_type
()
>=
tt_symbolic
||
src
==
arg
.
basic_type
(),
"sanity"
);
arglist
[
0
]
=
arg
;
// outgoing 'this'
arglist
[
1
]
=
ArgToken
();
// sentinel
arg
=
make_invoke
(
NULL
,
iid
,
Bytecodes
::
_invokestatic
,
false
,
1
,
&
arglist
[
0
],
CHECK
);
arg
=
make_invoke
(
methodHandle
()
,
iid
,
Bytecodes
::
_invokestatic
,
false
,
1
,
&
arglist
[
0
],
CHECK
);
change_argument
(
src
,
slot
,
dst
,
arg
);
}
else
{
// return type conversion
klassOop
arg_klass
=
NULL
;
arglist
[
0
]
=
make_parameter
(
src
,
arg_klass
,
-
1
,
CHECK
);
// return value
arglist
[
1
]
=
ArgToken
();
// sentinel
(
void
)
make_invoke
(
NULL
,
iid
,
Bytecodes
::
_invokestatic
,
false
,
1
,
&
arglist
[
0
],
CHECK
);
if
(
_return_conv
==
vmIntrinsics
::
_none
)
{
_return_conv
=
iid
;
}
else
if
(
_return_conv
==
vmIntrinsics
::
for_raw_conversion
(
dst
,
src
))
{
_return_conv
=
vmIntrinsics
::
_none
;
}
else
if
(
_return_conv
!=
zero_return_conv
())
{
lose
(
err_msg
(
"requested raw return conversion not allowed: %s -> %s (before %s)"
,
type2name
(
src
),
type2name
(
dst
),
vmIntrinsics
::
name_at
(
_return_conv
)),
CHECK
);
}
}
}
else
{
// Nothing to do.
}
}
else
if
(
for_return
&&
(
!
is_subword_type
(
src
)
||
!
is_subword_type
(
dst
)))
{
// This can occur in exception-throwing MHs, which have a fictitious return value encoded as Void or Empty.
_return_conv
=
zero_return_conv
();
}
else
if
(
src
==
T_OBJECT
&&
is_java_primitive
(
dst
))
{
// ref-to-prim: discard ref, push zero
lose
(
"requested ref-to-prim conversion not expected"
,
CHECK
);
...
...
@@ -896,6 +904,7 @@ MethodHandleCompiler::MethodHandleCompiler(Handle root, Symbol* name, Symbol* si
_thread
(
THREAD
),
_bytecode
(
THREAD
,
50
),
_constants
(
THREAD
,
10
),
_non_bcp_klasses
(
THREAD
,
5
),
_cur_stack
(
0
),
_max_stack
(
0
),
_rtype
(
T_ILLEGAL
)
...
...
@@ -908,6 +917,15 @@ MethodHandleCompiler::MethodHandleCompiler(Handle root, Symbol* name, Symbol* si
_name_index
=
cpool_symbol_put
(
name
);
_signature_index
=
cpool_symbol_put
(
signature
);
// To make the resulting methods more recognizable by
// stack walkers and compiler heuristics,
// we put them in holder class MethodHandle.
// See klass_is_method_handle_adapter_holder
// and methodOopDesc::is_method_handle_adapter.
_target_klass
=
SystemDictionaryHandles
::
MethodHandle_klass
();
check_non_bcp_klasses
(
java_lang_invoke_MethodHandle
::
type
(
root
()),
CHECK
);
// Get return type klass.
Handle
first_mtype
(
THREAD
,
chain
().
method_type_oop
());
// _rklass is NULL for primitives.
...
...
@@ -929,6 +947,7 @@ methodHandle MethodHandleCompiler::compile(TRAPS) {
assert
(
_thread
==
THREAD
,
"must be same thread"
);
methodHandle
nullHandle
;
(
void
)
walk
(
CHECK_
(
nullHandle
));
record_non_bcp_klasses
();
return
get_method_oop
(
CHECK_
(
nullHandle
));
}
...
...
@@ -1197,10 +1216,18 @@ void MethodHandleCompiler::emit_load_constant(ArgToken arg) {
}
case
T_OBJECT
:
{
Handle
value
=
arg
.
object
();
if
(
value
.
is_null
())
if
(
value
.
is_null
())
{
emit_bc
(
Bytecodes
::
_aconst_null
);
else
emit_bc
(
Bytecodes
::
_ldc
,
cpool_object_put
(
value
));
break
;
}
if
(
java_lang_Class
::
is_instance
(
value
()))
{
klassOop
k
=
java_lang_Class
::
as_klassOop
(
value
());
if
(
k
!=
NULL
)
{
emit_bc
(
Bytecodes
::
_ldc
,
cpool_klass_put
(
k
));
break
;
}
}
emit_bc
(
Bytecodes
::
_ldc
,
cpool_object_put
(
value
));
break
;
}
default:
...
...
@@ -1260,6 +1287,7 @@ MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Co
index
=
src
.
index
();
}
emit_bc
(
op
,
cpool_klass_put
(
tk
));
check_non_bcp_klass
(
tk
,
CHECK_
(
src
));
// Allocate a new local for the type so that we don't hide the
// previous type from the verifier.
index
=
new_local_index
(
type
);
...
...
@@ -1292,15 +1320,15 @@ jvalue MethodHandleCompiler::one_jvalue = { 1 };
// Emit bytecodes for the given invoke instruction.
MethodHandleWalker
::
ArgToken
MethodHandleCompiler
::
make_invoke
(
method
Oop
m
,
vmIntrinsics
::
ID
iid
,
MethodHandleCompiler
::
make_invoke
(
method
Handle
m
,
vmIntrinsics
::
ID
iid
,
Bytecodes
::
Code
op
,
bool
tailcall
,
int
argc
,
MethodHandleWalker
::
ArgToken
*
argv
,
TRAPS
)
{
ArgToken
zero
;
if
(
m
==
NULL
)
{
if
(
m
.
is_null
()
)
{
// Get the intrinsic methodOop.
m
=
vmIntrinsics
::
method_for
(
iid
);
if
(
m
==
NULL
)
{
m
=
methodHandle
(
THREAD
,
vmIntrinsics
::
method_for
(
iid
)
);
if
(
m
.
is_null
()
)
{
lose
(
vmIntrinsics
::
name_at
(
iid
),
CHECK_
(
zero
));
}
}
...
...
@@ -1309,18 +1337,46 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
Symbol
*
name
=
m
->
name
();
Symbol
*
signature
=
m
->
signature
();
if
(
iid
==
vmIntrinsics
::
_invokeGeneric
&&
argc
>=
1
&&
argv
[
0
].
token_type
()
==
tt_constant
)
{
assert
(
m
->
intrinsic_id
()
==
vmIntrinsics
::
_invokeExact
,
""
);
Handle
receiver
=
argv
[
0
].
object
();
Handle
rtype
(
THREAD
,
java_lang_invoke_MethodHandle
::
type
(
receiver
()));
Handle
mtype
(
THREAD
,
m
->
method_handle_type
());
if
(
rtype
()
!=
mtype
())
{
assert
(
java_lang_invoke_MethodType
::
form
(
rtype
())
==
java_lang_invoke_MethodType
::
form
(
mtype
()),
"must be the same shape"
);
// customize m to the exact required rtype
bool
has_non_bcp_klass
=
check_non_bcp_klasses
(
rtype
(),
CHECK_
(
zero
));
TempNewSymbol
sig2
=
java_lang_invoke_MethodType
::
as_signature
(
rtype
(),
true
,
CHECK_
(
zero
));
methodHandle
m2
;
if
(
!
has_non_bcp_klass
)
{
methodOop
m2_oop
=
SystemDictionary
::
find_method_handle_invoke
(
m
->
name
(),
sig2
,
KlassHandle
(),
CHECK_
(
zero
));
m2
=
methodHandle
(
THREAD
,
m2_oop
);
}
if
(
m2
.
is_null
())
{
// just build it fresh
m2
=
methodOopDesc
::
make_invoke_method
(
klass
,
m
->
name
(),
sig2
,
rtype
,
CHECK_
(
zero
));
if
(
m2
.
is_null
())
lose
(
err_msg
(
"no customized invoker %s"
,
sig2
->
as_utf8
()),
CHECK_
(
zero
));
}
m
=
m2
;
signature
=
m
->
signature
();
}
}
check_non_bcp_klass
(
klass
,
CHECK_
(
zero
));
if
(
m
->
is_method_handle_invoke
())
{
check_non_bcp_klasses
(
m
->
method_handle_type
(),
CHECK_
(
zero
));
}
// Count the number of arguments, not the size
ArgumentCount
asc
(
signature
);
assert
(
argc
==
asc
.
size
()
+
((
op
==
Bytecodes
::
_invokestatic
||
op
==
Bytecodes
::
_invokedynamic
)
?
0
:
1
),
"argc mismatch"
);
if
(
tailcall
)
{
// Actually, in order to make these methods more recognizable,
// let's put them in holder class MethodHandle. That way stack
// walkers and compiler heuristics can recognize them.
_target_klass
=
SystemDictionary
::
MethodHandle_klass
();
}
// Inline the method.
InvocationCounter
*
ic
=
m
->
invocation_counter
();
ic
->
set_carry_flag
();
...
...
@@ -1353,7 +1409,7 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
int
signature_index
=
cpool_symbol_put
(
signature
);
int
name_and_type_index
=
cpool_name_and_type_put
(
name_index
,
signature_index
);
int
klass_index
=
cpool_klass_put
(
klass
);
int
methodref_index
=
cpool_methodref_put
(
klass_index
,
name_and_type_index
);
int
methodref_index
=
cpool_methodref_put
(
op
,
klass_index
,
name_and_type_index
,
m
);
// Generate invoke.
switch
(
op
)
{
...
...
@@ -1380,6 +1436,20 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
stack_push
(
rbt
);
// The return value is already pushed onto the stack.
ArgToken
ret
;
if
(
tailcall
)
{
if
(
return_conv
()
==
zero_return_conv
())
{
rbt
=
T_VOID
;
// discard value
}
else
if
(
return_conv
()
!=
vmIntrinsics
::
_none
)
{
// return value conversion
int
index
=
new_local_index
(
rbt
);
emit_store
(
rbt
,
index
);
ArgToken
arglist
[
2
];
arglist
[
0
]
=
ArgToken
(
tt_temporary
,
rbt
,
index
);
arglist
[
1
]
=
ArgToken
();
// sentinel
ret
=
make_invoke
(
methodHandle
(),
return_conv
(),
Bytecodes
::
_invokestatic
,
false
,
1
,
&
arglist
[
0
],
CHECK_
(
zero
));
set_return_conv
(
vmIntrinsics
::
_none
);
rbt
=
ret
.
basic_type
();
emit_load
(
rbt
,
ret
.
index
());
}
if
(
rbt
!=
_rtype
)
{
if
(
rbt
==
T_VOID
)
{
// push a zero of the right sort
...
...
@@ -1425,6 +1495,7 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
case
T_OBJECT
:
if
(
_rklass
.
not_null
()
&&
_rklass
()
!=
SystemDictionary
::
Object_klass
()
&&
!
Klass
::
cast
(
_rklass
())
->
is_interface
())
{
emit_bc
(
Bytecodes
::
_checkcast
,
cpool_klass_put
(
_rklass
()));
check_non_bcp_klass
(
_rklass
(),
CHECK_
(
zero
));
}
emit_bc
(
Bytecodes
::
_areturn
);
break
;
...
...
@@ -1525,6 +1596,52 @@ int MethodHandleCompiler::cpool_primitive_put(BasicType bt, jvalue* con) {
return
index
;
}
bool
MethodHandleCompiler
::
check_non_bcp_klasses
(
Handle
method_type
,
TRAPS
)
{
bool
res
=
false
;
for
(
int
i
=
-
1
,
len
=
java_lang_invoke_MethodType
::
ptype_count
(
method_type
());
i
<
len
;
i
++
)
{
oop
ptype
=
(
i
==
-
1
?
java_lang_invoke_MethodType
::
rtype
(
method_type
())
:
java_lang_invoke_MethodType
::
ptype
(
method_type
(),
i
));
res
|=
check_non_bcp_klass
(
java_lang_Class
::
as_klassOop
(
ptype
),
CHECK_
(
false
));
}
return
res
;
}
bool
MethodHandleCompiler
::
check_non_bcp_klass
(
klassOop
klass
,
TRAPS
)
{
klass
=
methodOopDesc
::
check_non_bcp_klass
(
klass
);
if
(
klass
!=
NULL
)
{
Symbol
*
name
=
Klass
::
cast
(
klass
)
->
name
();
for
(
int
i
=
_non_bcp_klasses
.
length
()
-
1
;
i
>=
0
;
i
--
)
{
klassOop
k2
=
_non_bcp_klasses
.
at
(
i
)();
if
(
Klass
::
cast
(
k2
)
->
name
()
==
name
)
{
if
(
k2
!=
klass
)
{
lose
(
err_msg
(
"unsupported klass name alias %s"
,
name
->
as_utf8
()),
THREAD
);
}
return
true
;
}
}
_non_bcp_klasses
.
append
(
KlassHandle
(
THREAD
,
klass
));
return
true
;
}
return
false
;
}
void
MethodHandleCompiler
::
record_non_bcp_klasses
()
{
// Append extra klasses to constant pool, to guide klass lookup.
for
(
int
k
=
0
;
k
<
_non_bcp_klasses
.
length
();
k
++
)
{
klassOop
non_bcp_klass
=
_non_bcp_klasses
.
at
(
k
)();
bool
add_to_cp
=
true
;
for
(
int
j
=
1
;
j
<
_constants
.
length
();
j
++
)
{
ConstantValue
*
cv
=
_constants
.
at
(
j
);
if
(
cv
!=
NULL
&&
cv
->
tag
()
==
JVM_CONSTANT_Class
&&
cv
->
klass_oop
()
==
non_bcp_klass
)
{
add_to_cp
=
false
;
break
;
}
}
if
(
add_to_cp
)
cpool_klass_put
(
non_bcp_klass
);
}
}
constantPoolHandle
MethodHandleCompiler
::
get_constant_pool
(
TRAPS
)
const
{
constantPoolHandle
nullHandle
;
...
...
@@ -1544,6 +1661,8 @@ constantPoolHandle MethodHandleCompiler::get_constant_pool(TRAPS) const {
case
JVM_CONSTANT_Double
:
cpool
->
double_at_put
(
i
,
cv
->
get_jdouble
()
);
break
;
case
JVM_CONSTANT_Class
:
cpool
->
klass_at_put
(
i
,
cv
->
klass_oop
()
);
break
;
case
JVM_CONSTANT_Methodref
:
cpool
->
method_at_put
(
i
,
cv
->
first_index
(),
cv
->
second_index
());
break
;
case
JVM_CONSTANT_InterfaceMethodref
:
cpool
->
interface_method_at_put
(
i
,
cv
->
first_index
(),
cv
->
second_index
());
break
;
case
JVM_CONSTANT_NameAndType
:
cpool
->
name_and_type_at_put
(
i
,
cv
->
first_index
(),
cv
->
second_index
());
break
;
case
JVM_CONSTANT_Object
:
cpool
->
object_at_put
(
i
,
cv
->
object_oop
()
);
break
;
default:
ShouldNotReachHere
();
...
...
@@ -1558,6 +1677,8 @@ constantPoolHandle MethodHandleCompiler::get_constant_pool(TRAPS) const {
}
}
cpool
->
set_preresolution
();
// Set the constant pool holder to the target method's class.
cpool
->
set_pool_holder
(
_target_klass
());
...
...
@@ -1606,6 +1727,33 @@ methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const {
Rewriter
::
rewrite
(
_target_klass
(),
cpool
,
methods
,
CHECK_
(
empty
));
// Use fake class.
Rewriter
::
relocate_and_link
(
_target_klass
(),
methods
,
CHECK_
(
empty
));
// Use fake class.
// Pre-resolve selected CP cache entries, to avoid problems with class loader scoping.
constantPoolCacheHandle
cpc
(
THREAD
,
cpool
->
cache
());
for
(
int
i
=
0
;
i
<
cpc
->
length
();
i
++
)
{
ConstantPoolCacheEntry
*
e
=
cpc
->
entry_at
(
i
);
assert
(
!
e
->
is_secondary_entry
(),
"no indy instructions in here, yet"
);
int
constant_pool_index
=
e
->
constant_pool_index
();
ConstantValue
*
cv
=
_constants
.
at
(
constant_pool_index
);
if
(
!
cv
->
has_linkage
())
continue
;
methodHandle
m
=
cv
->
linkage
();
int
index
;
switch
(
cv
->
tag
())
{
case
JVM_CONSTANT_Methodref
:
index
=
m
->
vtable_index
();
if
(
m
->
is_static
())
{
e
->
set_method
(
Bytecodes
::
_invokestatic
,
m
,
index
);
}
else
{
e
->
set_method
(
Bytecodes
::
_invokespecial
,
m
,
index
);
e
->
set_method
(
Bytecodes
::
_invokevirtual
,
m
,
index
);
}
break
;
case
JVM_CONSTANT_InterfaceMethodref
:
index
=
klassItable
::
compute_itable_index
(
m
());
e
->
set_interface_call
(
m
,
index
);
break
;
}
}
// Set the invocation counter's count to the invoke count of the
// original call site.
InvocationCounter
*
ic
=
m
->
invocation_counter
();
...
...
@@ -1696,6 +1844,9 @@ public:
_param_state
(
0
),
_temp_num
(
0
)
{
out
->
print
(
"MethodHandle:"
);
java_lang_invoke_MethodType
::
print_signature
(
java_lang_invoke_MethodHandle
::
type
(
root
()),
out
);
out
->
print
(
" : #"
);
start_params
();
}
virtual
ArgToken
make_parameter
(
BasicType
type
,
klassOop
tk
,
int
argnum
,
TRAPS
)
{
...
...
@@ -1759,12 +1910,12 @@ public:
_strbuf
.
print
(
")"
);
return
maybe_make_temp
(
"fetch"
,
type
,
"x"
);
}
virtual
ArgToken
make_invoke
(
method
Oop
m
,
vmIntrinsics
::
ID
iid
,
virtual
ArgToken
make_invoke
(
method
Handle
m
,
vmIntrinsics
::
ID
iid
,
Bytecodes
::
Code
op
,
bool
tailcall
,
int
argc
,
ArgToken
*
argv
,
TRAPS
)
{
Symbol
*
name
;
Symbol
*
sig
;
if
(
m
!=
NULL
)
{
if
(
m
.
not_null
()
)
{
name
=
m
->
name
();
sig
=
m
->
signature
();
}
else
{
...
...
src/share/vm/prims/methodHandleWalk.hpp
浏览文件 @
50f0f018
...
...
@@ -98,6 +98,7 @@ public:
int
bound_arg_slot
()
{
assert
(
is_bound
(),
""
);
return
_arg_slot
;
}
oop
bound_arg_oop
()
{
assert
(
is_bound
(),
""
);
return
BoundMethodHandle_argument_oop
();
}
methodHandle
last_method
()
{
assert
(
is_last
(),
""
);
return
_last_method
;
}
methodOop
last_method_oop
()
{
assert
(
is_last
(),
""
);
return
_last_method
();
}
Bytecodes
::
Code
last_invoke_code
()
{
assert
(
is_last
(),
""
);
return
_last_invoke
;
}
...
...
@@ -181,6 +182,8 @@ private:
GrowableArray
<
ArgToken
>
_outgoing
;
// current outgoing parameter slots
int
_outgoing_argc
;
// # non-empty outgoing slots
vmIntrinsics
::
ID
_return_conv
;
// Return conversion required by raw retypes.
// Replace a value of type old_type at slot (and maybe slot+1) with the new value.
// If old_type != T_VOID, remove the old argument at that point.
// If new_type != T_VOID, insert the new argument at that point.
...
...
@@ -219,7 +222,8 @@ public:
:
_chain
(
root
,
THREAD
),
_for_invokedynamic
(
for_invokedynamic
),
_outgoing
(
THREAD
,
10
),
_outgoing_argc
(
0
)
_outgoing_argc
(
0
),
_return_conv
(
vmIntrinsics
::
_none
)
{
_local_index
=
for_invokedynamic
?
0
:
1
;
}
...
...
@@ -228,6 +232,10 @@ public:
bool
for_invokedynamic
()
const
{
return
_for_invokedynamic
;
}
vmIntrinsics
::
ID
return_conv
()
const
{
return
_return_conv
;
}
void
set_return_conv
(
vmIntrinsics
::
ID
c
)
{
_return_conv
=
c
;
}
static
vmIntrinsics
::
ID
zero_return_conv
()
{
return
vmIntrinsics
::
_min
;
}
int
new_local_index
(
BasicType
bt
)
{
//int index = _for_invokedynamic ? _local_index : _local_index - 1;
int
index
=
_local_index
;
...
...
@@ -243,9 +251,9 @@ public:
virtual
ArgToken
make_oop_constant
(
oop
con
,
TRAPS
)
=
0
;
virtual
ArgToken
make_conversion
(
BasicType
type
,
klassOop
tk
,
Bytecodes
::
Code
op
,
const
ArgToken
&
src
,
TRAPS
)
=
0
;
virtual
ArgToken
make_fetch
(
BasicType
type
,
klassOop
tk
,
Bytecodes
::
Code
op
,
const
ArgToken
&
base
,
const
ArgToken
&
offset
,
TRAPS
)
=
0
;
virtual
ArgToken
make_invoke
(
method
Oop
m
,
vmIntrinsics
::
ID
iid
,
Bytecodes
::
Code
op
,
bool
tailcall
,
int
argc
,
ArgToken
*
argv
,
TRAPS
)
=
0
;
virtual
ArgToken
make_invoke
(
method
Handle
m
,
vmIntrinsics
::
ID
iid
,
Bytecodes
::
Code
op
,
bool
tailcall
,
int
argc
,
ArgToken
*
argv
,
TRAPS
)
=
0
;
// For make_invoke, the method
Oop
can be NULL if the intrinsic ID
// For make_invoke, the method
Handle
can be NULL if the intrinsic ID
// is something other than vmIntrinsics::_none.
// and in case anyone cares to related the previous actions to the chain:
...
...
@@ -280,6 +288,7 @@ private:
JavaValue
_value
;
Handle
_handle
;
Symbol
*
_sym
;
methodHandle
_method
;
// pre-linkage
public:
// Constructor for oop types.
...
...
@@ -328,11 +337,21 @@ private:
jlong
get_jlong
()
const
{
return
_value
.
get_jlong
();
}
jfloat
get_jfloat
()
const
{
return
_value
.
get_jfloat
();
}
jdouble
get_jdouble
()
const
{
return
_value
.
get_jdouble
();
}
void
set_linkage
(
methodHandle
method
)
{
assert
(
_method
.
is_null
(),
""
);
_method
=
method
;
}
bool
has_linkage
()
const
{
return
_method
.
not_null
();
}
methodHandle
linkage
()
const
{
return
_method
;
}
};
// Fake constant pool.
GrowableArray
<
ConstantValue
*>
_constants
;
// Non-BCP classes that appear in associated MethodTypes (require special handling).
GrowableArray
<
KlassHandle
>
_non_bcp_klasses
;
// Accumulated compiler state:
GrowableArray
<
unsigned
char
>
_bytecode
;
...
...
@@ -368,15 +387,20 @@ private:
return
_constants
.
append
(
cv
);
}
int
cpool_oop_reference_put
(
int
tag
,
int
first_index
,
int
second_index
)
{
int
cpool_oop_reference_put
(
int
tag
,
int
first_index
,
int
second_index
,
methodHandle
method
)
{
if
(
first_index
==
0
&&
second_index
==
0
)
return
0
;
assert
(
first_index
!=
0
&&
second_index
!=
0
,
"no zero indexes"
);
ConstantValue
*
cv
=
new
ConstantValue
(
tag
,
first_index
,
second_index
);
if
(
method
.
not_null
())
cv
->
set_linkage
(
method
);
return
_constants
.
append
(
cv
);
}
int
cpool_primitive_put
(
BasicType
type
,
jvalue
*
con
);
bool
check_non_bcp_klasses
(
Handle
method_type
,
TRAPS
);
bool
check_non_bcp_klass
(
klassOop
klass
,
TRAPS
);
void
record_non_bcp_klasses
();
int
cpool_int_put
(
jint
value
)
{
jvalue
con
;
con
.
i
=
value
;
return
cpool_primitive_put
(
T_INT
,
&
con
);
...
...
@@ -403,11 +427,12 @@ private:
int
cpool_klass_put
(
klassOop
klass
)
{
return
cpool_oop_put
(
JVM_CONSTANT_Class
,
klass
);
}
int
cpool_methodref_put
(
int
class_index
,
int
name_and_type_index
)
{
return
cpool_oop_reference_put
(
JVM_CONSTANT_Methodref
,
class_index
,
name_and_type_index
);
int
cpool_methodref_put
(
Bytecodes
::
Code
op
,
int
class_index
,
int
name_and_type_index
,
methodHandle
method
)
{
int
tag
=
(
op
==
Bytecodes
::
_invokeinterface
?
JVM_CONSTANT_InterfaceMethodref
:
JVM_CONSTANT_Methodref
);
return
cpool_oop_reference_put
(
tag
,
class_index
,
name_and_type_index
,
method
);
}
int
cpool_name_and_type_put
(
int
name_index
,
int
signature_index
)
{
return
cpool_oop_reference_put
(
JVM_CONSTANT_NameAndType
,
name_index
,
signature_index
);
return
cpool_oop_reference_put
(
JVM_CONSTANT_NameAndType
,
name_index
,
signature_index
,
methodHandle
()
);
}
void
emit_bc
(
Bytecodes
::
Code
op
,
int
index
=
0
,
int
args_size
=
-
1
);
...
...
@@ -428,7 +453,7 @@ private:
virtual
ArgToken
make_conversion
(
BasicType
type
,
klassOop
tk
,
Bytecodes
::
Code
op
,
const
ArgToken
&
src
,
TRAPS
);
virtual
ArgToken
make_fetch
(
BasicType
type
,
klassOop
tk
,
Bytecodes
::
Code
op
,
const
ArgToken
&
base
,
const
ArgToken
&
offset
,
TRAPS
);
virtual
ArgToken
make_invoke
(
method
Oop
m
,
vmIntrinsics
::
ID
iid
,
Bytecodes
::
Code
op
,
bool
tailcall
,
int
argc
,
ArgToken
*
argv
,
TRAPS
);
virtual
ArgToken
make_invoke
(
method
Handle
m
,
vmIntrinsics
::
ID
iid
,
Bytecodes
::
Code
op
,
bool
tailcall
,
int
argc
,
ArgToken
*
argv
,
TRAPS
);
// Get a real constant pool.
constantPoolHandle
get_constant_pool
(
TRAPS
)
const
;
...
...
src/share/vm/prims/methodHandles.cpp
浏览文件 @
50f0f018
...
...
@@ -24,12 +24,14 @@
#include "precompiled.hpp"
#include "classfile/symbolTable.hpp"
#include "compiler/compileBroker.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/oopMapCache.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/oopFactory.hpp"
#include "prims/methodHandles.hpp"
#include "prims/methodHandleWalk.hpp"
#include "runtime/compilationPolicy.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/reflection.hpp"
#include "runtime/signature.hpp"
...
...
@@ -767,7 +769,9 @@ void MethodHandles::resolve_MemberName(Handle mname, TRAPS) {
m
=
NULL
;
// try again with a different class loader...
}
if
(
m
!=
NULL
)
{
if
(
m
!=
NULL
&&
m
->
is_method_handle_invoke
()
&&
java_lang_invoke_MethodType
::
equals
(
polymorphic_method_type
(),
m
->
method_handle_type
()))
{
int
mods
=
(
m
->
access_flags
().
as_short
()
&
JVM_RECOGNIZED_METHOD_MODIFIERS
);
java_lang_invoke_MemberName
::
set_vmtarget
(
mname
(),
m
);
java_lang_invoke_MemberName
::
set_vmindex
(
mname
(),
m
->
vtable_index
());
...
...
@@ -986,6 +990,48 @@ instanceKlassHandle MethodHandles::resolve_instance_klass(oop java_mirror_oop, T
// This is for debugging and reflection.
oop
MethodHandles
::
encode_target
(
Handle
mh
,
int
format
,
TRAPS
)
{
assert
(
java_lang_invoke_MethodHandle
::
is_instance
(
mh
()),
"must be a MH"
);
if
(
format
==
ETF_FORCE_DIRECT_HANDLE
||
format
==
ETF_COMPILE_DIRECT_HANDLE
)
{
// Internal function for stress testing.
Handle
mt
=
java_lang_invoke_MethodHandle
::
type
(
mh
());
int
invocation_count
=
10000
;
TempNewSymbol
signature
=
java_lang_invoke_MethodType
::
as_signature
(
mt
(),
true
,
CHECK_NULL
);
bool
omit_receiver_argument
=
true
;
MethodHandleCompiler
mhc
(
mh
,
vmSymbols
::
invoke_name
(),
signature
,
invocation_count
,
omit_receiver_argument
,
CHECK_NULL
);
methodHandle
m
=
mhc
.
compile
(
CHECK_NULL
);
if
(
StressMethodHandleWalk
&&
Verbose
||
PrintMiscellaneous
)
{
tty
->
print_cr
(
"MethodHandleNatives.getTarget(%s)"
,
format
==
ETF_FORCE_DIRECT_HANDLE
?
"FORCE_DIRECT"
:
"COMPILE_DIRECT"
);
if
(
Verbose
)
{
m
->
print_codes
();
}
}
if
(
StressMethodHandleWalk
)
{
InterpreterOopMap
mask
;
OopMapCache
::
compute_one_oop_map
(
m
,
m
->
code_size
()
-
1
,
&
mask
);
}
if
((
format
==
ETF_COMPILE_DIRECT_HANDLE
||
CompilationPolicy
::
must_be_compiled
(
m
))
&&
!
instanceKlass
::
cast
(
m
->
method_holder
())
->
is_not_initialized
()
&&
CompilationPolicy
::
can_be_compiled
(
m
))
{
// Force compilation
CompileBroker
::
compile_method
(
m
,
InvocationEntryBci
,
CompLevel_initial_compile
,
methodHandle
(),
0
,
"MethodHandleNatives.getTarget"
,
CHECK_NULL
);
}
// Now wrap m in a DirectMethodHandle.
instanceKlassHandle
dmh_klass
(
THREAD
,
SystemDictionary
::
DirectMethodHandle_klass
());
Handle
dmh
=
dmh_klass
->
allocate_instance_handle
(
CHECK_NULL
);
JavaValue
ignore_result
(
T_VOID
);
Symbol
*
init_name
=
vmSymbols
::
object_initializer_name
();
Symbol
*
init_sig
=
vmSymbols
::
notifyGenericMethodType_signature
();
JavaCalls
::
call_special
(
&
ignore_result
,
dmh
,
SystemDictionaryHandles
::
MethodHandle_klass
(),
init_name
,
init_sig
,
java_lang_invoke_MethodHandle
::
type
(
mh
()),
CHECK_NULL
);
MethodHandles
::
init_DirectMethodHandle
(
dmh
,
m
,
false
,
CHECK_NULL
);
return
dmh
();
}
if
(
format
==
ETF_HANDLE_OR_METHOD_NAME
)
{
oop
target
=
java_lang_invoke_MethodHandle
::
vmtarget
(
mh
());
if
(
target
==
NULL
)
{
...
...
@@ -1221,6 +1267,12 @@ void MethodHandles::verify_method_signature(methodHandle m,
klassOop
aklass_oop
=
SystemDictionary
::
resolve_or_null
(
name
,
loader
,
domain
,
CHECK
);
if
(
aklass_oop
!=
NULL
)
aklass
=
KlassHandle
(
THREAD
,
aklass_oop
);
if
(
aklass
.
is_null
()
&&
pklass
.
not_null
()
&&
loader
.
is_null
()
&&
pklass
->
name
()
==
name
)
// accept name equivalence here, since that's the best we can do
aklass
=
pklass
;
}
}
else
{
// for method handle invokers we don't look at the name in the signature
...
...
@@ -2654,6 +2706,17 @@ static void stress_method_handle_walk_impl(Handle mh, TRAPS) {
}
InterpreterOopMap
mask
;
OopMapCache
::
compute_one_oop_map
(
m
,
m
->
code_size
()
-
1
,
&
mask
);
// compile to object code if -Xcomp or WizardMode
if
((
WizardMode
||
CompilationPolicy
::
must_be_compiled
(
m
))
&&
!
instanceKlass
::
cast
(
m
->
method_holder
())
->
is_not_initialized
()
&&
CompilationPolicy
::
can_be_compiled
(
m
))
{
// Force compilation
CompileBroker
::
compile_method
(
m
,
InvocationEntryBci
,
CompLevel_initial_compile
,
methodHandle
(),
0
,
"StressMethodHandleWalk"
,
CHECK
);
}
}
}
...
...
@@ -2773,7 +2836,12 @@ JVM_ENTRY(void, MHN_init_BMH(JNIEnv *env, jobject igcls, jobject mh_jh,
// Build a BMH on top of a DMH or another BMH:
MethodHandles
::
init_BoundMethodHandle
(
mh
,
target
,
argnum
,
CHECK
);
}
stress_method_handle_walk
(
mh
,
CHECK
);
if
(
StressMethodHandleWalk
)
{
if
(
mh
->
klass
()
==
SystemDictionary
::
BoundMethodHandle_klass
())
stress_method_handle_walk
(
mh
,
CHECK
);
// else don't, since the subclass has not yet initialized its own fields
}
}
JVM_END
...
...
src/share/vm/prims/methodHandles.hpp
浏览文件 @
50f0f018
...
...
@@ -588,6 +588,8 @@ class MethodHandles: AllStatic {
ETF_DIRECT_HANDLE
=
1
,
// ultimate method handle (will be a DMH, may be self)
ETF_METHOD_NAME
=
2
,
// ultimate method as MemberName
ETF_REFLECT_METHOD
=
3
,
// ultimate method as java.lang.reflect object (sans refClass)
ETF_FORCE_DIRECT_HANDLE
=
64
,
ETF_COMPILE_DIRECT_HANDLE
=
65
,
// ad hoc constants
OP_ROT_ARGS_DOWN_LIMIT_BIAS
=
-
1
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录