96
97 methodOop last_method_oop() { assert(is_last(), ""); return _last_method(); }
98 Bytecodes::Code last_invoke_code() { assert(is_last(), ""); return _last_invoke; }
99
100 void lose(const char* msg, TRAPS);
101 const char* lose_message() { return _lose_message; }
102 };
103
104
105 // Structure walker for method handles.
106 // Does abstract interpretation on top of low-level parsing.
107 // You supply the tokens shuffled by the abstract interpretation.
108 class MethodHandleWalker : StackObj {
109 public:
110 // Stack values:
111 enum TokenType {
112 tt_void,
113 tt_parameter,
114 tt_temporary,
115 tt_constant,
116 tt_illegal
117 };
118
119 // Argument token:
120 class ArgToken {
121 private:
122 TokenType _tt;
123 BasicType _bt;
124 jvalue _value;
125 Handle _handle;
126
127 public:
128 ArgToken(TokenType tt = tt_illegal) : _tt(tt) {}
129 ArgToken(TokenType tt, BasicType bt, jvalue value) : _tt(tt), _bt(bt), _value(value) {}
130
131 ArgToken(TokenType tt, BasicType bt, int index) : _tt(tt), _bt(bt) {
132 _value.i = index;
133 }
134
135 ArgToken(TokenType tt, BasicType bt, Handle value) : _tt(tt), _bt(bt) {
147 jdouble get_jdouble() const { return _value.d; }
148 };
149
150 // Abstract interpretation state:
151 struct SlotState {
152 BasicType _type;
153 ArgToken _arg;
154 SlotState() : _type(), _arg() {}
155 };
156 static SlotState make_state(BasicType type, ArgToken arg) {
157 SlotState ss;
158 ss._type = type; ss._arg = arg;
159 return ss;
160 }
161
162 private:
163 MethodHandleChain _chain;
164 bool _for_invokedynamic;
165 int _local_index;
166
167 GrowableArray<SlotState> _outgoing; // current outgoing parameter slots
168 int _outgoing_argc; // # non-empty outgoing slots
169
170 // Replace a value of type old_type at slot (and maybe slot+1) with the new value.
171 // If old_type != T_VOID, remove the old argument at that point.
172 // If new_type != T_VOID, insert the new argument at that point.
173 // Insert or delete a second empty slot as needed.
174 void change_argument(BasicType old_type, int slot, BasicType new_type, const ArgToken& new_arg);
175
176 SlotState* slot_state(int slot) {
177 if (slot < 0 || slot >= _outgoing.length())
178 return NULL;
179 return _outgoing.adr_at(slot);
180 }
181 BasicType slot_type(int slot) {
182 SlotState* ss = slot_state(slot);
183 if (ss == NULL)
184 return T_ILLEGAL;
185 return ss->_type;
186 }
187 bool slot_has_argument(int slot) {
188 return slot_type(slot) < T_VOID;
189 }
190
191 #ifdef ASSERT
192 int argument_count_slow();
193 #endif
194
195 // Return a bytecode for converting src to dest, if one exists.
204 _outgoing(THREAD, 10),
205 _outgoing_argc(0)
206 {
207 _local_index = for_invokedynamic ? 0 : 1;
208 }
209
210 MethodHandleChain& chain() { return _chain; }
211
212 bool for_invokedynamic() const { return _for_invokedynamic; }
213
214 int new_local_index(BasicType bt) {
215 //int index = _for_invokedynamic ? _local_index : _local_index - 1;
216 int index = _local_index;
217 _local_index += type2size[bt];
218 return index;
219 }
220
221 int max_locals() const { return _local_index; }
222
223 // plug-in abstract interpretation steps:
224 virtual ArgToken make_parameter( BasicType type, klassOop tk, int argnum, TRAPS ) = 0;
225 virtual ArgToken make_prim_constant( BasicType type, jvalue* con, TRAPS ) = 0;
226 virtual ArgToken make_oop_constant( oop con, TRAPS ) = 0;
227 virtual ArgToken make_conversion( BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS ) = 0;
228 virtual ArgToken make_fetch( BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS ) = 0;
229 virtual ArgToken make_invoke( methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS ) = 0;
230
231 // For make_invoke, the methodOop can be NULL if the intrinsic ID
232 // is something other than vmIntrinsics::_none.
233
234 // and in case anyone cares to related the previous actions to the chain:
235 virtual void set_method_handle(oop mh) { }
236
237 void lose(const char* msg, TRAPS) { chain().lose(msg, THREAD); }
238 const char* lose_message() { return chain().lose_message(); }
239
240 ArgToken walk(TRAPS);
241 };
242
243
244 // An abstract interpreter for method handle chains.
245 // Produces an account of the semantics of a chain, in terms of a static IR.
246 // The IR happens to be JVM bytecodes.
247 class MethodHandleCompiler : public MethodHandleWalker {
248 private:
249 methodHandle _callee;
250 int _invoke_count; // count the original call site has been executed
251 KlassHandle _rklass; // Return type for casting.
252 BasicType _rtype;
253 KlassHandle _target_klass;
254 Thread* _thread;
255
256 // Fake constant pool entry.
257 class ConstantValue {
258 private:
259 int _tag; // Constant pool tag type.
260 JavaValue _value;
261 Handle _handle;
262 Symbol* _sym;
263
264 public:
265 // Constructor for oop types.
266 ConstantValue(int tag, Handle con) : _tag(tag), _handle(con) {
267 assert(tag == JVM_CONSTANT_Class ||
268 tag == JVM_CONSTANT_String ||
269 tag == JVM_CONSTANT_Object, "must be oop type");
270 }
271
272 ConstantValue(int tag, Symbol* con) : _tag(tag), _sym(con) {
273 assert(tag == JVM_CONSTANT_Utf8, "must be symbol type");
274 }
275
400 }
401 virtual ArgToken make_oop_constant(oop con, TRAPS) {
402 Handle h(THREAD, con);
403 return ArgToken(tt_constant, T_OBJECT, h);
404 }
405 virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) {
406 return ArgToken(tt_constant, type, *con);
407 }
408
409 virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS);
410 virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS);
411 virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS);
412
413 // Get a real constant pool.
414 constantPoolHandle get_constant_pool(TRAPS) const;
415
416 // Get a real methodOop.
417 methodHandle get_method_oop(TRAPS) const;
418
419 public:
420 MethodHandleCompiler(Handle root, methodHandle call_method, int invoke_count, bool for_invokedynamic, TRAPS);
421
422 // Compile the given MH chain into bytecode.
423 methodHandle compile(TRAPS);
424
425 // Tests if the given class is a MH adapter holder.
426 static bool klass_is_method_handle_adapter_holder(klassOop klass) {
427 return (klass == SystemDictionary::MethodHandle_klass());
428 }
429 };
430
431 #endif // SHARE_VM_PRIMS_METHODHANDLEWALK_HPP
|
96
97 methodOop last_method_oop() { assert(is_last(), ""); return _last_method(); }
98 Bytecodes::Code last_invoke_code() { assert(is_last(), ""); return _last_invoke; }
99
100 void lose(const char* msg, TRAPS);
101 const char* lose_message() { return _lose_message; }
102 };
103
104
105 // Structure walker for method handles.
106 // Does abstract interpretation on top of low-level parsing.
107 // You supply the tokens shuffled by the abstract interpretation.
108 class MethodHandleWalker : StackObj {
109 public:
110 // Stack values:
111 enum TokenType {
112 tt_void,
113 tt_parameter,
114 tt_temporary,
115 tt_constant,
116 tt_symbolic,
117 tt_illegal
118 };
119
120 // Argument token:
121 class ArgToken {
122 private:
123 TokenType _tt;
124 BasicType _bt;
125 jvalue _value;
126 Handle _handle;
127
128 public:
129 ArgToken(TokenType tt = tt_illegal) : _tt(tt) {}
130 ArgToken(TokenType tt, BasicType bt, jvalue value) : _tt(tt), _bt(bt), _value(value) {}
131
132 ArgToken(TokenType tt, BasicType bt, int index) : _tt(tt), _bt(bt) {
133 _value.i = index;
134 }
135
136 ArgToken(TokenType tt, BasicType bt, Handle value) : _tt(tt), _bt(bt) {
148 jdouble get_jdouble() const { return _value.d; }
149 };
150
151 // Abstract interpretation state:
152 struct SlotState {
153 BasicType _type;
154 ArgToken _arg;
155 SlotState() : _type(), _arg() {}
156 };
157 static SlotState make_state(BasicType type, ArgToken arg) {
158 SlotState ss;
159 ss._type = type; ss._arg = arg;
160 return ss;
161 }
162
163 private:
164 MethodHandleChain _chain;
165 bool _for_invokedynamic;
166 int _local_index;
167
168 // This array is kept in an unusual order, indexed by low-level "slot number".
169 // TOS is always _outgoing.at(0), so simple pushes and pops shift the whole _outgoing array.
170 // If there is a receiver in the current argument list, it is at _outgoing.at(_outgoing.length()-1).
171 // If a value at _outgoing.at(n) is T_LONG or T_DOUBLE, the value at _outgoing.at(n+1) is T_VOID.
172 GrowableArray<SlotState> _outgoing; // current outgoing parameter slots
173 int _outgoing_argc; // # non-empty outgoing slots
174
175 // Replace a value of type old_type at slot (and maybe slot+1) with the new value.
176 // If old_type != T_VOID, remove the old argument at that point.
177 // If new_type != T_VOID, insert the new argument at that point.
178 // Insert or delete a second empty slot as needed.
179 void change_argument(BasicType old_type, int slot, BasicType new_type, const ArgToken& new_arg);
180
181 // Raw retype conversions for OP_RAW_RETYPE.
182 void retype_raw_conversion(BasicType src, BasicType dst, bool for_return, int slot, TRAPS);
183 void retype_raw_argument_type(BasicType src, BasicType dst, int slot, TRAPS) { retype_raw_conversion(src, dst, false, slot, CHECK); }
184 void retype_raw_return_type( BasicType src, BasicType dst, TRAPS) { retype_raw_conversion(src, dst, true, -1, CHECK); }
185
186 SlotState* slot_state(int slot) {
187 if (slot < 0 || slot >= _outgoing.length())
188 return NULL;
189 return _outgoing.adr_at(slot);
190 }
191 BasicType slot_type(int slot) {
192 SlotState* ss = slot_state(slot);
193 if (ss == NULL)
194 return T_ILLEGAL;
195 return ss->_type;
196 }
197 bool slot_has_argument(int slot) {
198 return slot_type(slot) < T_VOID;
199 }
200
201 #ifdef ASSERT
202 int argument_count_slow();
203 #endif
204
205 // Return a bytecode for converting src to dest, if one exists.
214 _outgoing(THREAD, 10),
215 _outgoing_argc(0)
216 {
217 _local_index = for_invokedynamic ? 0 : 1;
218 }
219
220 MethodHandleChain& chain() { return _chain; }
221
222 bool for_invokedynamic() const { return _for_invokedynamic; }
223
224 int new_local_index(BasicType bt) {
225 //int index = _for_invokedynamic ? _local_index : _local_index - 1;
226 int index = _local_index;
227 _local_index += type2size[bt];
228 return index;
229 }
230
231 int max_locals() const { return _local_index; }
232
233 // plug-in abstract interpretation steps:
234 virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) = 0;
235 virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) = 0;
236 virtual ArgToken make_oop_constant(oop con, TRAPS) = 0;
237 virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS) = 0;
238 virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS) = 0;
239 virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS) = 0;
240
241 // For make_invoke, the methodOop can be NULL if the intrinsic ID
242 // is something other than vmIntrinsics::_none.
243
244 // and in case anyone cares to related the previous actions to the chain:
245 virtual void set_method_handle(oop mh) { }
246
247 void lose(const char* msg, TRAPS) { chain().lose(msg, THREAD); }
248 const char* lose_message() { return chain().lose_message(); }
249
250 ArgToken walk(TRAPS);
251 };
252
253
254 // An abstract interpreter for method handle chains.
255 // Produces an account of the semantics of a chain, in terms of a static IR.
256 // The IR happens to be JVM bytecodes.
257 class MethodHandleCompiler : public MethodHandleWalker {
258 private:
259 methodHandle _callee;
260 int _invoke_count; // count the original call site has been executed
261 KlassHandle _rklass; // Return type for casting.
262 BasicType _rtype;
263 KlassHandle _target_klass;
264 Thread* _thread;
265
266 // Values used by the compiler.
267 static jvalue zero_jvalue;
268 static jvalue one_jvalue;
269
270 // Fake constant pool entry.
271 class ConstantValue {
272 private:
273 int _tag; // Constant pool tag type.
274 JavaValue _value;
275 Handle _handle;
276 Symbol* _sym;
277
278 public:
279 // Constructor for oop types.
280 ConstantValue(int tag, Handle con) : _tag(tag), _handle(con) {
281 assert(tag == JVM_CONSTANT_Class ||
282 tag == JVM_CONSTANT_String ||
283 tag == JVM_CONSTANT_Object, "must be oop type");
284 }
285
286 ConstantValue(int tag, Symbol* con) : _tag(tag), _sym(con) {
287 assert(tag == JVM_CONSTANT_Utf8, "must be symbol type");
288 }
289
414 }
415 virtual ArgToken make_oop_constant(oop con, TRAPS) {
416 Handle h(THREAD, con);
417 return ArgToken(tt_constant, T_OBJECT, h);
418 }
419 virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) {
420 return ArgToken(tt_constant, type, *con);
421 }
422
423 virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS);
424 virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS);
425 virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS);
426
427 // Get a real constant pool.
428 constantPoolHandle get_constant_pool(TRAPS) const;
429
430 // Get a real methodOop.
431 methodHandle get_method_oop(TRAPS) const;
432
433 public:
434 MethodHandleCompiler(Handle root, methodHandle callee, int invoke_count, bool for_invokedynamic, TRAPS);
435
436 // Compile the given MH chain into bytecode.
437 methodHandle compile(TRAPS);
438
439 // Tests if the given class is a MH adapter holder.
440 static bool klass_is_method_handle_adapter_holder(klassOop klass) {
441 return (klass == SystemDictionary::MethodHandle_klass());
442 }
443 };
444
445 #endif // SHARE_VM_PRIMS_METHODHANDLEWALK_HPP
|