comparison src/share/vm/prims/methodHandleWalk.hpp @ 3740:5ac411b3b8fc

7047961: JSR 292 MethodHandleWalk swap args doesn't handle T_LONG and T_DOUBLE properly Reviewed-by: kvn, jrose
author never
date Thu, 26 May 2011 14:44:41 -0700
parents a80577f854f9
children f7d55ea6ee56
comparison
equal deleted inserted replaced
3738:c7c81f18c834 3740:5ac411b3b8fc
54 int DirectMethodHandle_vmindex() { return java_lang_invoke_DirectMethodHandle::vmindex(method_handle_oop()); } 54 int DirectMethodHandle_vmindex() { return java_lang_invoke_DirectMethodHandle::vmindex(method_handle_oop()); }
55 oop BoundMethodHandle_argument_oop() { return java_lang_invoke_BoundMethodHandle::argument(method_handle_oop()); } 55 oop BoundMethodHandle_argument_oop() { return java_lang_invoke_BoundMethodHandle::argument(method_handle_oop()); }
56 int BoundMethodHandle_vmargslot() { return java_lang_invoke_BoundMethodHandle::vmargslot(method_handle_oop()); } 56 int BoundMethodHandle_vmargslot() { return java_lang_invoke_BoundMethodHandle::vmargslot(method_handle_oop()); }
57 int AdapterMethodHandle_conversion() { return java_lang_invoke_AdapterMethodHandle::conversion(method_handle_oop()); } 57 int AdapterMethodHandle_conversion() { return java_lang_invoke_AdapterMethodHandle::conversion(method_handle_oop()); }
58 58
59 #ifdef ASSERT
60 void print_impl(TRAPS);
61 #endif
62
59 public: 63 public:
60 MethodHandleChain(Handle root, TRAPS) 64 MethodHandleChain(Handle root, TRAPS)
61 : _root(root) 65 : _root(root)
62 { set_method_handle(root, THREAD); } 66 { set_method_handle(root, THREAD); }
63 67
97 methodOop last_method_oop() { assert(is_last(), ""); return _last_method(); } 101 methodOop last_method_oop() { assert(is_last(), ""); return _last_method(); }
98 Bytecodes::Code last_invoke_code() { assert(is_last(), ""); return _last_invoke; } 102 Bytecodes::Code last_invoke_code() { assert(is_last(), ""); return _last_invoke; }
99 103
100 void lose(const char* msg, TRAPS); 104 void lose(const char* msg, TRAPS);
101 const char* lose_message() { return _lose_message; } 105 const char* lose_message() { return _lose_message; }
106
107 #ifdef ASSERT
108 // Print a symbolic description of a method handle chain, including
109 // the signature for each method. The signatures are printed in
110 // slot order to make it easier to understand.
111 void print();
112 static void print(Handle mh);
113 #endif
102 }; 114 };
103 115
104 116
105 // Structure walker for method handles. 117 // Structure walker for method handles.
106 // Does abstract interpretation on top of low-level parsing. 118 // Does abstract interpretation on top of low-level parsing.
124 BasicType _bt; 136 BasicType _bt;
125 jvalue _value; 137 jvalue _value;
126 Handle _handle; 138 Handle _handle;
127 139
128 public: 140 public:
129 ArgToken(TokenType tt = tt_illegal) : _tt(tt) { 141 ArgToken(TokenType tt = tt_illegal) : _tt(tt), _bt(tt == tt_void ? T_VOID : T_ILLEGAL) {
130 assert(tt == tt_illegal || tt == tt_void, "invalid token type"); 142 assert(tt == tt_illegal || tt == tt_void, "invalid token type");
131 } 143 }
132 144
133 ArgToken(TokenType tt, BasicType bt, int index) : _tt(tt), _bt(bt) { 145 ArgToken(TokenType tt, BasicType bt, int index) : _tt(tt), _bt(bt) {
134 assert(_tt == tt_parameter || _tt == tt_temporary, "must have index"); 146 assert(_tt == tt_parameter || _tt == tt_temporary, "must have index");
135 _value.i = index; 147 _value.i = index;
136 } 148 }
137 149
138 ArgToken(BasicType bt, jvalue value) : _tt(tt_constant), _bt(bt), _value(value) {} 150 ArgToken(BasicType bt, jvalue value) : _tt(tt_constant), _bt(bt), _value(value) { assert(_bt != T_OBJECT, "wrong constructor"); }
139 ArgToken(BasicType bt, Handle value) : _tt(tt_constant), _bt(bt), _handle(value) {} 151 ArgToken(Handle handle) : _tt(tt_constant), _bt(T_OBJECT), _handle(handle) {}
140 152
141 153
142 ArgToken(const char* str) : _tt(tt_symbolic), _bt(T_LONG) { 154 ArgToken(const char* str, BasicType type) : _tt(tt_symbolic), _bt(type) {
143 _value.j = (intptr_t)str; 155 _value.j = (intptr_t)str;
144 } 156 }
145 157
146 TokenType token_type() const { return _tt; } 158 TokenType token_type() const { return _tt; }
147 BasicType basic_type() const { return _bt; } 159 BasicType basic_type() const { return _bt; }
148 bool has_index() const { return _tt == tt_parameter || _tt == tt_temporary; } 160 bool has_index() const { return _tt == tt_parameter || _tt == tt_temporary; }
149 int index() const { assert(has_index(), "must have index");; return _value.i; } 161 int index() const { assert(has_index(), "must have index");; return _value.i; }
150 Handle object() const { assert(_tt == tt_constant, "value type"); return _handle; } 162 Handle object() const { assert(_bt == T_OBJECT, "wrong accessor"); assert(_tt == tt_constant, "value type"); return _handle; }
151 const char* str() const { assert(_tt == tt_symbolic, "string type"); return (const char*)_value.j; } 163 const char* str() const { assert(_tt == tt_symbolic, "string type"); return (const char*)(intptr_t)_value.j; }
152 164
153 jint get_jint() const { assert(_tt == tt_constant, "value types"); return _value.i; } 165 jint get_jint() const { assert(_bt == T_INT || is_subword_type(_bt), "wrong accessor"); assert(_tt == tt_constant, "value types"); return _value.i; }
154 jlong get_jlong() const { assert(_tt == tt_constant, "value types"); return _value.j; } 166 jlong get_jlong() const { assert(_bt == T_LONG, "wrong accessor"); assert(_tt == tt_constant, "value types"); return _value.j; }
155 jfloat get_jfloat() const { assert(_tt == tt_constant, "value types"); return _value.f; } 167 jfloat get_jfloat() const { assert(_bt == T_FLOAT, "wrong accessor"); assert(_tt == tt_constant, "value types"); return _value.f; }
156 jdouble get_jdouble() const { assert(_tt == tt_constant, "value types"); return _value.d; } 168 jdouble get_jdouble() const { assert(_bt == T_DOUBLE, "wrong accessor"); assert(_tt == tt_constant, "value types"); return _value.d; }
157 }; 169 };
158
159 // Abstract interpretation state:
160 struct SlotState {
161 BasicType _type;
162 ArgToken _arg;
163 SlotState() : _type(), _arg() {}
164 };
165 static SlotState make_state(BasicType type, ArgToken arg) {
166 SlotState ss;
167 ss._type = type; ss._arg = arg;
168 return ss;
169 }
170 170
171 private: 171 private:
172 MethodHandleChain _chain; 172 MethodHandleChain _chain;
173 bool _for_invokedynamic; 173 bool _for_invokedynamic;
174 int _local_index; 174 int _local_index;
175 175
176 // This array is kept in an unusual order, indexed by low-level "slot number". 176 // This array is kept in an unusual order, indexed by low-level "slot number".
177 // TOS is always _outgoing.at(0), so simple pushes and pops shift the whole _outgoing array. 177 // TOS is always _outgoing.at(0), so simple pushes and pops shift the whole _outgoing array.
178 // If there is a receiver in the current argument list, it is at _outgoing.at(_outgoing.length()-1). 178 // If there is a receiver in the current argument list, it is at _outgoing.at(_outgoing.length()-1).
179 // If a value at _outgoing.at(n) is T_LONG or T_DOUBLE, the value at _outgoing.at(n+1) is T_VOID. 179 // If a value at _outgoing.at(n) is T_LONG or T_DOUBLE, the value at _outgoing.at(n+1) is T_VOID.
180 GrowableArray<SlotState> _outgoing; // current outgoing parameter slots 180 GrowableArray<ArgToken> _outgoing; // current outgoing parameter slots
181 int _outgoing_argc; // # non-empty outgoing slots 181 int _outgoing_argc; // # non-empty outgoing slots
182 182
183 // Replace a value of type old_type at slot (and maybe slot+1) with the new value. 183 // Replace a value of type old_type at slot (and maybe slot+1) with the new value.
184 // If old_type != T_VOID, remove the old argument at that point. 184 // If old_type != T_VOID, remove the old argument at that point.
185 // If new_type != T_VOID, insert the new argument at that point. 185 // If new_type != T_VOID, insert the new argument at that point.
186 // Insert or delete a second empty slot as needed. 186 // Insert or delete a second empty slot as needed.
187 void change_argument(BasicType old_type, int slot, BasicType new_type, const ArgToken& new_arg); 187 void change_argument(BasicType old_type, int slot, const ArgToken& new_arg);
188 void change_argument(BasicType old_type, int slot, BasicType type, const ArgToken& new_arg) {
189 assert(type == new_arg.basic_type(), "must agree");
190 change_argument(old_type, slot, new_arg);
191 }
188 192
189 // Raw retype conversions for OP_RAW_RETYPE. 193 // Raw retype conversions for OP_RAW_RETYPE.
190 void retype_raw_conversion(BasicType src, BasicType dst, bool for_return, int slot, TRAPS); 194 void retype_raw_conversion(BasicType src, BasicType dst, bool for_return, int slot, TRAPS);
191 void retype_raw_argument_type(BasicType src, BasicType dst, int slot, TRAPS) { retype_raw_conversion(src, dst, false, slot, CHECK); } 195 void retype_raw_argument_type(BasicType src, BasicType dst, int slot, TRAPS) { retype_raw_conversion(src, dst, false, slot, CHECK); }
192 void retype_raw_return_type( BasicType src, BasicType dst, TRAPS) { retype_raw_conversion(src, dst, true, -1, CHECK); } 196 void retype_raw_return_type( BasicType src, BasicType dst, TRAPS) { retype_raw_conversion(src, dst, true, -1, CHECK); }
193 197
194 SlotState* slot_state(int slot) { 198 BasicType arg_type(int slot) {
195 if (slot < 0 || slot >= _outgoing.length()) 199 return _outgoing.at(slot).basic_type();
196 return NULL; 200 }
197 return _outgoing.adr_at(slot); 201 bool has_argument(int slot) {
198 } 202 return arg_type(slot) < T_VOID;
199 BasicType slot_type(int slot) {
200 SlotState* ss = slot_state(slot);
201 if (ss == NULL)
202 return T_ILLEGAL;
203 return ss->_type;
204 }
205 bool slot_has_argument(int slot) {
206 return slot_type(slot) < T_VOID;
207 } 203 }
208 204
209 #ifdef ASSERT 205 #ifdef ASSERT
210 int argument_count_slow(); 206 int argument_count_slow();
211 #endif 207 #endif
212 208
213 // Return a bytecode for converting src to dest, if one exists. 209 // Return a bytecode for converting src to dest, if one exists.
214 Bytecodes::Code conversion_code(BasicType src, BasicType dest); 210 Bytecodes::Code conversion_code(BasicType src, BasicType dest);
215 211
216 void walk_incoming_state(TRAPS); 212 void walk_incoming_state(TRAPS);
213
214 void verify_args_and_signature(TRAPS) NOT_DEBUG_RETURN;
217 215
218 public: 216 public:
219 MethodHandleWalker(Handle root, bool for_invokedynamic, TRAPS) 217 MethodHandleWalker(Handle root, bool for_invokedynamic, TRAPS)
220 : _chain(root, THREAD), 218 : _chain(root, THREAD),
221 _for_invokedynamic(for_invokedynamic), 219 _for_invokedynamic(for_invokedynamic),
419 virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) { 417 virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) {
420 return ArgToken(tt_parameter, type, argnum); 418 return ArgToken(tt_parameter, type, argnum);
421 } 419 }
422 virtual ArgToken make_oop_constant(oop con, TRAPS) { 420 virtual ArgToken make_oop_constant(oop con, TRAPS) {
423 Handle h(THREAD, con); 421 Handle h(THREAD, con);
424 return ArgToken(T_OBJECT, h); 422 return ArgToken(h);
425 } 423 }
426 virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) { 424 virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) {
427 return ArgToken(type, *con); 425 return ArgToken(type, *con);
428 } 426 }
429 427