提交 730a6a98 编写于 作者: N never

7047961: JSR 292 MethodHandleWalk swap args doesn't handle T_LONG and T_DOUBLE properly

Reviewed-by: kvn, jrose
上级 7c843ca5
...@@ -56,6 +56,10 @@ private: ...@@ -56,6 +56,10 @@ private:
int BoundMethodHandle_vmargslot() { return java_lang_invoke_BoundMethodHandle::vmargslot(method_handle_oop()); } int BoundMethodHandle_vmargslot() { return java_lang_invoke_BoundMethodHandle::vmargslot(method_handle_oop()); }
int AdapterMethodHandle_conversion() { return java_lang_invoke_AdapterMethodHandle::conversion(method_handle_oop()); } int AdapterMethodHandle_conversion() { return java_lang_invoke_AdapterMethodHandle::conversion(method_handle_oop()); }
#ifdef ASSERT
void print_impl(TRAPS);
#endif
public: public:
MethodHandleChain(Handle root, TRAPS) MethodHandleChain(Handle root, TRAPS)
: _root(root) : _root(root)
...@@ -99,6 +103,14 @@ public: ...@@ -99,6 +103,14 @@ public:
void lose(const char* msg, TRAPS); void lose(const char* msg, TRAPS);
const char* lose_message() { return _lose_message; } const char* lose_message() { return _lose_message; }
#ifdef ASSERT
// Print a symbolic description of a method handle chain, including
// the signature for each method. The signatures are printed in
// slot order to make it easier to understand.
void print();
static void print(Handle mh);
#endif
}; };
...@@ -126,7 +138,7 @@ public: ...@@ -126,7 +138,7 @@ public:
Handle _handle; Handle _handle;
public: public:
ArgToken(TokenType tt = tt_illegal) : _tt(tt) { ArgToken(TokenType tt = tt_illegal) : _tt(tt), _bt(tt == tt_void ? T_VOID : T_ILLEGAL) {
assert(tt == tt_illegal || tt == tt_void, "invalid token type"); assert(tt == tt_illegal || tt == tt_void, "invalid token type");
} }
...@@ -135,11 +147,11 @@ public: ...@@ -135,11 +147,11 @@ public:
_value.i = index; _value.i = index;
} }
ArgToken(BasicType bt, jvalue value) : _tt(tt_constant), _bt(bt), _value(value) {} ArgToken(BasicType bt, jvalue value) : _tt(tt_constant), _bt(bt), _value(value) { assert(_bt != T_OBJECT, "wrong constructor"); }
ArgToken(BasicType bt, Handle value) : _tt(tt_constant), _bt(bt), _handle(value) {} ArgToken(Handle handle) : _tt(tt_constant), _bt(T_OBJECT), _handle(handle) {}
ArgToken(const char* str) : _tt(tt_symbolic), _bt(T_LONG) { ArgToken(const char* str, BasicType type) : _tt(tt_symbolic), _bt(type) {
_value.j = (intptr_t)str; _value.j = (intptr_t)str;
} }
...@@ -147,27 +159,15 @@ public: ...@@ -147,27 +159,15 @@ public:
BasicType basic_type() const { return _bt; } BasicType basic_type() const { return _bt; }
bool has_index() const { return _tt == tt_parameter || _tt == tt_temporary; } bool has_index() const { return _tt == tt_parameter || _tt == tt_temporary; }
int index() const { assert(has_index(), "must have index");; return _value.i; } int index() const { assert(has_index(), "must have index");; return _value.i; }
Handle object() const { assert(_tt == tt_constant, "value type"); return _handle; } Handle object() const { assert(_bt == T_OBJECT, "wrong accessor"); assert(_tt == tt_constant, "value type"); return _handle; }
const char* str() const { assert(_tt == tt_symbolic, "string type"); return (const char*)_value.j; } const char* str() const { assert(_tt == tt_symbolic, "string type"); return (const char*)(intptr_t)_value.j; }
jint get_jint() const { assert(_tt == tt_constant, "value types"); return _value.i; } jint get_jint() const { assert(_bt == T_INT || is_subword_type(_bt), "wrong accessor"); assert(_tt == tt_constant, "value types"); return _value.i; }
jlong get_jlong() const { assert(_tt == tt_constant, "value types"); return _value.j; } jlong get_jlong() const { assert(_bt == T_LONG, "wrong accessor"); assert(_tt == tt_constant, "value types"); return _value.j; }
jfloat get_jfloat() const { assert(_tt == tt_constant, "value types"); return _value.f; } jfloat get_jfloat() const { assert(_bt == T_FLOAT, "wrong accessor"); assert(_tt == tt_constant, "value types"); return _value.f; }
jdouble get_jdouble() const { assert(_tt == tt_constant, "value types"); return _value.d; } jdouble get_jdouble() const { assert(_bt == T_DOUBLE, "wrong accessor"); assert(_tt == tt_constant, "value types"); return _value.d; }
}; };
// Abstract interpretation state:
struct SlotState {
BasicType _type;
ArgToken _arg;
SlotState() : _type(), _arg() {}
};
static SlotState make_state(BasicType type, ArgToken arg) {
SlotState ss;
ss._type = type; ss._arg = arg;
return ss;
}
private: private:
MethodHandleChain _chain; MethodHandleChain _chain;
bool _for_invokedynamic; bool _for_invokedynamic;
...@@ -177,33 +177,29 @@ private: ...@@ -177,33 +177,29 @@ private:
// TOS is always _outgoing.at(0), so simple pushes and pops shift the whole _outgoing array. // TOS is always _outgoing.at(0), so simple pushes and pops shift the whole _outgoing array.
// If there is a receiver in the current argument list, it is at _outgoing.at(_outgoing.length()-1). // If there is a receiver in the current argument list, it is at _outgoing.at(_outgoing.length()-1).
// If a value at _outgoing.at(n) is T_LONG or T_DOUBLE, the value at _outgoing.at(n+1) is T_VOID. // If a value at _outgoing.at(n) is T_LONG or T_DOUBLE, the value at _outgoing.at(n+1) is T_VOID.
GrowableArray<SlotState> _outgoing; // current outgoing parameter slots GrowableArray<ArgToken> _outgoing; // current outgoing parameter slots
int _outgoing_argc; // # non-empty outgoing slots int _outgoing_argc; // # non-empty outgoing slots
// Replace a value of type old_type at slot (and maybe slot+1) with the new value. // 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 old_type != T_VOID, remove the old argument at that point.
// If new_type != T_VOID, insert the new argument at that point. // If new_type != T_VOID, insert the new argument at that point.
// Insert or delete a second empty slot as needed. // Insert or delete a second empty slot as needed.
void change_argument(BasicType old_type, int slot, BasicType new_type, const ArgToken& new_arg); void change_argument(BasicType old_type, int slot, const ArgToken& new_arg);
void change_argument(BasicType old_type, int slot, BasicType type, const ArgToken& new_arg) {
assert(type == new_arg.basic_type(), "must agree");
change_argument(old_type, slot, new_arg);
}
// Raw retype conversions for OP_RAW_RETYPE. // Raw retype conversions for OP_RAW_RETYPE.
void retype_raw_conversion(BasicType src, BasicType dst, bool for_return, int slot, TRAPS); void retype_raw_conversion(BasicType src, BasicType dst, bool for_return, int slot, TRAPS);
void retype_raw_argument_type(BasicType src, BasicType dst, int slot, TRAPS) { retype_raw_conversion(src, dst, false, slot, CHECK); } void retype_raw_argument_type(BasicType src, BasicType dst, int slot, TRAPS) { retype_raw_conversion(src, dst, false, slot, CHECK); }
void retype_raw_return_type( BasicType src, BasicType dst, TRAPS) { retype_raw_conversion(src, dst, true, -1, CHECK); } void retype_raw_return_type( BasicType src, BasicType dst, TRAPS) { retype_raw_conversion(src, dst, true, -1, CHECK); }
SlotState* slot_state(int slot) { BasicType arg_type(int slot) {
if (slot < 0 || slot >= _outgoing.length()) return _outgoing.at(slot).basic_type();
return NULL;
return _outgoing.adr_at(slot);
}
BasicType slot_type(int slot) {
SlotState* ss = slot_state(slot);
if (ss == NULL)
return T_ILLEGAL;
return ss->_type;
} }
bool slot_has_argument(int slot) { bool has_argument(int slot) {
return slot_type(slot) < T_VOID; return arg_type(slot) < T_VOID;
} }
#ifdef ASSERT #ifdef ASSERT
...@@ -215,6 +211,8 @@ private: ...@@ -215,6 +211,8 @@ private:
void walk_incoming_state(TRAPS); void walk_incoming_state(TRAPS);
void verify_args_and_signature(TRAPS) NOT_DEBUG_RETURN;
public: public:
MethodHandleWalker(Handle root, bool for_invokedynamic, TRAPS) MethodHandleWalker(Handle root, bool for_invokedynamic, TRAPS)
: _chain(root, THREAD), : _chain(root, THREAD),
...@@ -421,7 +419,7 @@ private: ...@@ -421,7 +419,7 @@ private:
} }
virtual ArgToken make_oop_constant(oop con, TRAPS) { virtual ArgToken make_oop_constant(oop con, TRAPS) {
Handle h(THREAD, con); Handle h(THREAD, con);
return ArgToken(T_OBJECT, h); return ArgToken(h);
} }
virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) { virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) {
return ArgToken(type, *con); return ArgToken(type, *con);
......
...@@ -1305,6 +1305,7 @@ void MethodHandles::verify_vmargslot(Handle mh, int argnum, int argslot, TRAPS) ...@@ -1305,6 +1305,7 @@ void MethodHandles::verify_vmargslot(Handle mh, int argnum, int argslot, TRAPS)
// Verify that argslot points at the given argnum. // Verify that argslot points at the given argnum.
int check_slot = argument_slot(java_lang_invoke_MethodHandle::type(mh()), argnum); int check_slot = argument_slot(java_lang_invoke_MethodHandle::type(mh()), argnum);
if (argslot != check_slot || argslot < 0) { if (argslot != check_slot || argslot < 0) {
ResourceMark rm;
const char* fmt = "for argnum of %d, vmargslot is %d, should be %d"; const char* fmt = "for argnum of %d, vmargslot is %d, should be %d";
size_t msglen = strlen(fmt) + 3*11 + 1; size_t msglen = strlen(fmt) + 3*11 + 1;
char* msg = NEW_RESOURCE_ARRAY(char, msglen); char* msg = NEW_RESOURCE_ARRAY(char, msglen);
...@@ -1829,6 +1830,7 @@ void MethodHandles::init_BoundMethodHandle(Handle mh, Handle target, int argnum, ...@@ -1829,6 +1830,7 @@ void MethodHandles::init_BoundMethodHandle(Handle mh, Handle target, int argnum,
bool direct_to_method = false; bool direct_to_method = false;
if (OptimizeMethodHandles && if (OptimizeMethodHandles &&
target->klass() == SystemDictionary::DirectMethodHandle_klass() && target->klass() == SystemDictionary::DirectMethodHandle_klass() &&
(argnum != 0 || java_lang_invoke_BoundMethodHandle::argument(mh()) != NULL) &&
(argnum == 0 || java_lang_invoke_DirectMethodHandle::vmindex(target()) < 0)) { (argnum == 0 || java_lang_invoke_DirectMethodHandle::vmindex(target()) < 0)) {
KlassHandle receiver_limit; int decode_flags = 0; KlassHandle receiver_limit; int decode_flags = 0;
methodHandle m = decode_method(target(), receiver_limit, decode_flags); methodHandle m = decode_method(target(), receiver_limit, decode_flags);
...@@ -1980,7 +1982,6 @@ void MethodHandles::verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS) { ...@@ -1980,7 +1982,6 @@ void MethodHandles::verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS) {
err = "adapter requires src/dest conversion subfields for swap"; break; err = "adapter requires src/dest conversion subfields for swap"; break;
} }
int swap_size = type2size[src]; int swap_size = type2size[src];
int slot_limit = java_lang_invoke_MethodHandle::vmslots(target());
int src_slot = argslot; int src_slot = argslot;
int dest_slot = vminfo; int dest_slot = vminfo;
bool rotate_up = (src_slot > dest_slot); // upward rotation bool rotate_up = (src_slot > dest_slot); // upward rotation
...@@ -2333,7 +2334,6 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu ...@@ -2333,7 +2334,6 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
case _adapter_rot_args: case _adapter_rot_args:
{ {
int swap_slots = type2size[src]; int swap_slots = type2size[src];
int slot_limit = java_lang_invoke_AdapterMethodHandle::vmslots(mh());
int src_slot = argslot; int src_slot = argslot;
int dest_slot = vminfo; int dest_slot = vminfo;
int rotate = (ek_orig == _adapter_swap_args) ? 0 : (src_slot > dest_slot) ? 1 : -1; int rotate = (ek_orig == _adapter_swap_args) ? 0 : (src_slot > dest_slot) ? 1 : -1;
...@@ -2661,14 +2661,14 @@ JVM_ENTRY(void, MHN_init_DMH(JNIEnv *env, jobject igcls, jobject mh_jh, ...@@ -2661,14 +2661,14 @@ JVM_ENTRY(void, MHN_init_DMH(JNIEnv *env, jobject igcls, jobject mh_jh,
ResourceMark rm; // for error messages ResourceMark rm; // for error messages
// This is the guy we are initializing: // This is the guy we are initializing:
if (mh_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } if (mh_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "self is null"); }
Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh)); Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh));
// Early returns out of this method leave the DMH in an unfinished state. // Early returns out of this method leave the DMH in an unfinished state.
assert(java_lang_invoke_MethodHandle::vmentry(mh()) == NULL, "must be safely null"); assert(java_lang_invoke_MethodHandle::vmentry(mh()) == NULL, "must be safely null");
// which method are we really talking about? // which method are we really talking about?
if (target_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } if (target_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "target is null"); }
Handle target(THREAD, JNIHandles::resolve_non_null(target_jh)); Handle target(THREAD, JNIHandles::resolve_non_null(target_jh));
if (java_lang_invoke_MemberName::is_instance(target()) && if (java_lang_invoke_MemberName::is_instance(target()) &&
java_lang_invoke_MemberName::vmindex(target()) == VM_INDEX_UNINITIALIZED) { java_lang_invoke_MemberName::vmindex(target()) == VM_INDEX_UNINITIALIZED) {
...@@ -2722,13 +2722,13 @@ JVM_ENTRY(void, MHN_init_BMH(JNIEnv *env, jobject igcls, jobject mh_jh, ...@@ -2722,13 +2722,13 @@ JVM_ENTRY(void, MHN_init_BMH(JNIEnv *env, jobject igcls, jobject mh_jh,
ResourceMark rm; // for error messages ResourceMark rm; // for error messages
// This is the guy we are initializing: // This is the guy we are initializing:
if (mh_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } if (mh_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "self is null"); }
Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh)); Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh));
// Early returns out of this method leave the BMH in an unfinished state. // Early returns out of this method leave the BMH in an unfinished state.
assert(java_lang_invoke_MethodHandle::vmentry(mh()) == NULL, "must be safely null"); assert(java_lang_invoke_MethodHandle::vmentry(mh()) == NULL, "must be safely null");
if (target_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } if (target_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "target is null"); }
Handle target(THREAD, JNIHandles::resolve_non_null(target_jh)); Handle target(THREAD, JNIHandles::resolve_non_null(target_jh));
if (!java_lang_invoke_MethodHandle::is_instance(target())) { if (!java_lang_invoke_MethodHandle::is_instance(target())) {
...@@ -2753,9 +2753,8 @@ JVM_END ...@@ -2753,9 +2753,8 @@ JVM_END
JVM_ENTRY(void, MHN_init_AMH(JNIEnv *env, jobject igcls, jobject mh_jh, JVM_ENTRY(void, MHN_init_AMH(JNIEnv *env, jobject igcls, jobject mh_jh,
jobject target_jh, int argnum)) { jobject target_jh, int argnum)) {
// This is the guy we are initializing: // This is the guy we are initializing:
if (mh_jh == NULL || target_jh == NULL) { if (mh_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "self is null"); }
THROW(vmSymbols::java_lang_InternalError()); if (target_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "target is null"); }
}
Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh)); Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh));
Handle target(THREAD, JNIHandles::resolve_non_null(target_jh)); Handle target(THREAD, JNIHandles::resolve_non_null(target_jh));
...@@ -2890,7 +2889,8 @@ JVM_END ...@@ -2890,7 +2889,8 @@ JVM_END
// void init(MemberName self, AccessibleObject ref) // void init(MemberName self, AccessibleObject ref)
JVM_ENTRY(void, MHN_init_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jobject target_jh)) { JVM_ENTRY(void, MHN_init_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jobject target_jh)) {
if (mname_jh == NULL || target_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } if (mname_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "mname is null"); }
if (target_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "target is null"); }
Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
oop target_oop = JNIHandles::resolve_non_null(target_jh); oop target_oop = JNIHandles::resolve_non_null(target_jh);
MethodHandles::init_MemberName(mname(), target_oop); MethodHandles::init_MemberName(mname(), target_oop);
...@@ -2899,7 +2899,7 @@ JVM_END ...@@ -2899,7 +2899,7 @@ JVM_END
// void expand(MemberName self) // void expand(MemberName self)
JVM_ENTRY(void, MHN_expand_Mem(JNIEnv *env, jobject igcls, jobject mname_jh)) { JVM_ENTRY(void, MHN_expand_Mem(JNIEnv *env, jobject igcls, jobject mname_jh)) {
if (mname_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } if (mname_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "mname is null"); }
Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
MethodHandles::expand_MemberName(mname, 0, CHECK); MethodHandles::expand_MemberName(mname, 0, CHECK);
} }
...@@ -2907,7 +2907,7 @@ JVM_END ...@@ -2907,7 +2907,7 @@ JVM_END
// void resolve(MemberName self, Class<?> caller) // void resolve(MemberName self, Class<?> caller)
JVM_ENTRY(void, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh)) { JVM_ENTRY(void, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh)) {
if (mname_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } if (mname_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "mname is null"); }
Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
// The trusted Java code that calls this method should already have performed // The trusted Java code that calls this method should already have performed
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册