Mercurial > hg > graal-jvmci-8
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 |