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), |