151 Bytecodes::Code conversion_code(BasicType src, BasicType dest); |
191 Bytecodes::Code conversion_code(BasicType src, BasicType dest); |
152 |
192 |
153 void walk_incoming_state(TRAPS); |
193 void walk_incoming_state(TRAPS); |
154 |
194 |
155 public: |
195 public: |
156 MethodHandleWalker(Handle root, TRAPS) |
196 MethodHandleWalker(Handle root, bool for_invokedynamic, TRAPS) |
157 : _chain(root, THREAD), |
197 : _chain(root, THREAD), |
|
198 _for_invokedynamic(for_invokedynamic), |
158 _outgoing(THREAD, 10), |
199 _outgoing(THREAD, 10), |
159 _outgoing_argc(0) |
200 _outgoing_argc(0) |
160 { } |
201 { |
|
202 _local_index = for_invokedynamic ? 0 : 1; |
|
203 } |
161 |
204 |
162 MethodHandleChain& chain() { return _chain; } |
205 MethodHandleChain& chain() { return _chain; } |
|
206 |
|
207 bool for_invokedynamic() const { return _for_invokedynamic; } |
|
208 |
|
209 int new_local_index(BasicType bt) { |
|
210 //int index = _for_invokedynamic ? _local_index : _local_index - 1; |
|
211 int index = _local_index; |
|
212 _local_index += type2size[bt]; |
|
213 return index; |
|
214 } |
|
215 |
|
216 int max_locals() const { return _local_index; } |
163 |
217 |
164 // plug-in abstract interpretation steps: |
218 // plug-in abstract interpretation steps: |
165 virtual ArgToken make_parameter( BasicType type, klassOop tk, int argnum, TRAPS ) = 0; |
219 virtual ArgToken make_parameter( BasicType type, klassOop tk, int argnum, TRAPS ) = 0; |
166 virtual ArgToken make_prim_constant( BasicType type, jvalue* con, TRAPS ) = 0; |
220 virtual ArgToken make_prim_constant( BasicType type, jvalue* con, TRAPS ) = 0; |
167 virtual ArgToken make_oop_constant( oop con, TRAPS ) = 0; |
221 virtual ArgToken make_oop_constant( oop con, TRAPS ) = 0; |
168 virtual ArgToken make_conversion( BasicType type, klassOop tk, Bytecodes::Code op, ArgToken src, TRAPS ) = 0; |
222 virtual ArgToken make_conversion( BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS ) = 0; |
169 virtual ArgToken make_fetch( BasicType type, klassOop tk, Bytecodes::Code op, ArgToken base, ArgToken offset, TRAPS ) = 0; |
223 virtual ArgToken make_fetch( BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS ) = 0; |
170 virtual ArgToken make_invoke( methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS ) = 0; |
224 virtual ArgToken make_invoke( methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS ) = 0; |
171 |
225 |
172 // For make_invoke, the methodOop can be NULL if the intrinsic ID |
226 // For make_invoke, the methodOop can be NULL if the intrinsic ID |
173 // is something other than vmIntrinsics::_none. |
227 // is something other than vmIntrinsics::_none. |
174 |
228 |
185 // An abstract interpreter for method handle chains. |
239 // An abstract interpreter for method handle chains. |
186 // Produces an account of the semantics of a chain, in terms of a static IR. |
240 // Produces an account of the semantics of a chain, in terms of a static IR. |
187 // The IR happens to be JVM bytecodes. |
241 // The IR happens to be JVM bytecodes. |
188 class MethodHandleCompiler : public MethodHandleWalker { |
242 class MethodHandleCompiler : public MethodHandleWalker { |
189 private: |
243 private: |
190 Thread* _thread; |
244 methodHandle _callee; |
191 |
245 KlassHandle _rklass; // Return type for casting. |
192 struct PrimCon { |
246 BasicType _rtype; |
193 BasicType _type; |
247 KlassHandle _target_klass; |
194 jvalue _value; |
248 Thread* _thread; |
|
249 |
|
250 // Fake constant pool entry. |
|
251 class ConstantValue { |
|
252 private: |
|
253 int _tag; // Constant pool tag type. |
|
254 JavaValue _value; |
|
255 Handle _handle; |
|
256 |
|
257 public: |
|
258 // Constructor for oop types. |
|
259 ConstantValue(int tag, Handle con) : _tag(tag), _handle(con) { |
|
260 assert(tag == JVM_CONSTANT_Utf8 || |
|
261 tag == JVM_CONSTANT_Class || |
|
262 tag == JVM_CONSTANT_String || |
|
263 tag == JVM_CONSTANT_Object, "must be oop type"); |
|
264 } |
|
265 |
|
266 // Constructor for oop reference types. |
|
267 ConstantValue(int tag, int index) : _tag(tag) { |
|
268 assert(JVM_CONSTANT_Fieldref <= tag && tag <= JVM_CONSTANT_NameAndType, "must be ref type"); |
|
269 _value.set_jint(index); |
|
270 } |
|
271 ConstantValue(int tag, int first_index, int second_index) : _tag(tag) { |
|
272 assert(JVM_CONSTANT_Fieldref <= tag && tag <= JVM_CONSTANT_NameAndType, "must be ref type"); |
|
273 _value.set_jint(first_index << 16 | second_index); |
|
274 } |
|
275 |
|
276 // Constructor for primitive types. |
|
277 ConstantValue(BasicType bt, jvalue con) { |
|
278 _value.set_type(bt); |
|
279 switch (bt) { |
|
280 case T_INT: _tag = JVM_CONSTANT_Integer; _value.set_jint( con.i); break; |
|
281 case T_LONG: _tag = JVM_CONSTANT_Long; _value.set_jlong( con.j); break; |
|
282 case T_FLOAT: _tag = JVM_CONSTANT_Float; _value.set_jfloat( con.f); break; |
|
283 case T_DOUBLE: _tag = JVM_CONSTANT_Double; _value.set_jdouble(con.d); break; |
|
284 default: ShouldNotReachHere(); |
|
285 } |
|
286 } |
|
287 |
|
288 int tag() const { return _tag; } |
|
289 symbolOop symbol_oop() const { return (symbolOop) _handle(); } |
|
290 klassOop klass_oop() const { return (klassOop) _handle(); } |
|
291 oop object_oop() const { return _handle(); } |
|
292 int index() const { return _value.get_jint(); } |
|
293 int first_index() const { return _value.get_jint() >> 16; } |
|
294 int second_index() const { return _value.get_jint() & 0x0000FFFF; } |
|
295 |
|
296 bool is_primitive() const { return is_java_primitive(_value.get_type()); } |
|
297 jint get_jint() const { return _value.get_jint(); } |
|
298 jlong get_jlong() const { return _value.get_jlong(); } |
|
299 jfloat get_jfloat() const { return _value.get_jfloat(); } |
|
300 jdouble get_jdouble() const { return _value.get_jdouble(); } |
195 }; |
301 }; |
196 |
302 |
|
303 // Fake constant pool. |
|
304 GrowableArray<ConstantValue*> _constants; |
|
305 |
197 // Accumulated compiler state: |
306 // Accumulated compiler state: |
198 stringStream _bytes; |
307 GrowableArray<unsigned char> _bytecode; |
199 GrowableArray<Handle> _constant_oops; |
308 |
200 GrowableArray<PrimCon*> _constant_prims; |
309 int _cur_stack; |
201 int _max_stack; |
310 int _max_stack; |
202 int _num_params; |
311 int _num_params; |
203 int _max_locals; |
|
204 int _name_index; |
312 int _name_index; |
205 int _signature_index; |
313 int _signature_index; |
206 |
314 |
207 // Stack values: |
315 void stack_push(BasicType bt) { |
208 enum TokenType { |
316 _cur_stack += type2size[bt]; |
209 tt_void, |
317 if (_cur_stack > _max_stack) _max_stack = _cur_stack; |
210 tt_parameter, |
318 } |
211 tt_temporary, |
319 void stack_pop(BasicType bt) { |
212 tt_constant |
320 _cur_stack -= type2size[bt]; |
213 }; |
321 assert(_cur_stack >= 0, "sanity"); |
214 |
322 } |
215 ArgToken make_stack_value(TokenType tt, BasicType type, int id) { |
323 |
216 return ArgToken( ((intptr_t)id << 8) | ((intptr_t)type << 4) | (intptr_t)tt ); |
324 unsigned char* bytecode() const { return _bytecode.adr_at(0); } |
217 } |
325 int bytecode_length() const { return _bytecode.length(); } |
|
326 |
|
327 // Fake constant pool. |
|
328 int cpool_oop_put(int tag, Handle con) { |
|
329 if (con.is_null()) return 0; |
|
330 ConstantValue* cv = new ConstantValue(tag, con); |
|
331 return _constants.append(cv); |
|
332 } |
|
333 |
|
334 int cpool_oop_reference_put(int tag, int first_index, int second_index) { |
|
335 if (first_index == 0 && second_index == 0) return 0; |
|
336 assert(first_index != 0 && second_index != 0, "no zero indexes"); |
|
337 ConstantValue* cv = new ConstantValue(tag, first_index, second_index); |
|
338 return _constants.append(cv); |
|
339 } |
|
340 |
|
341 int cpool_primitive_put(BasicType type, jvalue* con); |
|
342 |
|
343 int cpool_int_put(jint value) { |
|
344 jvalue con; con.i = value; |
|
345 return cpool_primitive_put(T_INT, &con); |
|
346 } |
|
347 int cpool_long_put(jlong value) { |
|
348 jvalue con; con.j = value; |
|
349 return cpool_primitive_put(T_LONG, &con); |
|
350 } |
|
351 int cpool_float_put(jfloat value) { |
|
352 jvalue con; con.f = value; |
|
353 return cpool_primitive_put(T_FLOAT, &con); |
|
354 } |
|
355 int cpool_double_put(jdouble value) { |
|
356 jvalue con; con.d = value; |
|
357 return cpool_primitive_put(T_DOUBLE, &con); |
|
358 } |
|
359 |
|
360 int cpool_object_put(Handle obj) { |
|
361 return cpool_oop_put(JVM_CONSTANT_Object, obj); |
|
362 } |
|
363 int cpool_symbol_put(symbolOop sym) { |
|
364 return cpool_oop_put(JVM_CONSTANT_Utf8, sym); |
|
365 } |
|
366 int cpool_klass_put(klassOop klass) { |
|
367 return cpool_oop_put(JVM_CONSTANT_Class, klass); |
|
368 } |
|
369 int cpool_methodref_put(int class_index, int name_and_type_index) { |
|
370 return cpool_oop_reference_put(JVM_CONSTANT_Methodref, class_index, name_and_type_index); |
|
371 } |
|
372 int cpool_name_and_type_put(int name_index, int signature_index) { |
|
373 return cpool_oop_reference_put(JVM_CONSTANT_NameAndType, name_index, signature_index); |
|
374 } |
|
375 |
|
376 void emit_bc(Bytecodes::Code op, int index = 0); |
|
377 void emit_load(BasicType bt, int index); |
|
378 void emit_store(BasicType bt, int index); |
|
379 void emit_load_constant(ArgToken arg); |
|
380 |
|
381 virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) { |
|
382 return ArgToken(tt_parameter, type, argnum); |
|
383 } |
|
384 virtual ArgToken make_oop_constant(oop con, TRAPS) { |
|
385 Handle h(THREAD, con); |
|
386 return ArgToken(tt_constant, T_OBJECT, h); |
|
387 } |
|
388 virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) { |
|
389 return ArgToken(tt_constant, type, *con); |
|
390 } |
|
391 |
|
392 virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS); |
|
393 virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS); |
|
394 virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS); |
|
395 |
|
396 // Get a real constant pool. |
|
397 constantPoolHandle get_constant_pool(TRAPS) const; |
|
398 |
|
399 // Get a real methodOop. |
|
400 methodHandle get_method_oop(TRAPS) const; |
218 |
401 |
219 public: |
402 public: |
220 virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) { |
403 MethodHandleCompiler(Handle root, methodHandle call_method, bool for_invokedynamic, TRAPS); |
221 return make_stack_value(tt_parameter, type, argnum); |
|
222 } |
|
223 virtual ArgToken make_oop_constant(oop con, TRAPS) { |
|
224 return make_stack_value(tt_constant, T_OBJECT, find_oop_constant(con)); |
|
225 } |
|
226 virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) { |
|
227 return make_stack_value(tt_constant, type, find_prim_constant(type, con)); |
|
228 } |
|
229 virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken src, TRAPS); |
|
230 virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken base, ArgToken offset, TRAPS); |
|
231 virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS); |
|
232 |
|
233 int find_oop_constant(oop con); |
|
234 int find_prim_constant(BasicType type, jvalue* con); |
|
235 |
|
236 public: |
|
237 MethodHandleCompiler(Handle root, TRAPS) |
|
238 : MethodHandleWalker(root, THREAD), |
|
239 _thread(THREAD), |
|
240 _bytes(50), |
|
241 _constant_oops(THREAD, 10), |
|
242 _constant_prims(THREAD, 10), |
|
243 _max_stack(0), _max_locals(0), |
|
244 _name_index(0), _signature_index(0) |
|
245 { } |
|
246 const char* bytes() { return _bytes.as_string(); } |
|
247 int constant_length() { return _constant_oops.length(); } |
|
248 int max_stack() { return _max_stack; } |
|
249 int max_locals() { return _max_locals; } |
|
250 int name_index() { return _name_index; } |
|
251 int signature_index() { return _signature_index; } |
|
252 symbolHandle name() { return symbolHandle(_thread, (symbolOop)constant_oop_at(_name_index)()); } |
|
253 symbolHandle signature() { return symbolHandle(_thread, (symbolOop)constant_oop_at(_signature_index)()); } |
|
254 |
|
255 bool constant_is_oop_at(int i) { |
|
256 return (_constant_prims.at(i) == NULL); |
|
257 } |
|
258 Handle constant_oop_at(int i) { |
|
259 assert(constant_is_oop_at(i), ""); |
|
260 return _constant_oops.at(i); |
|
261 } |
|
262 PrimCon* constant_prim_at(int i) { |
|
263 assert(!constant_is_oop_at(i), ""); |
|
264 return _constant_prims.at(i); |
|
265 } |
|
266 |
404 |
267 // Compile the given MH chain into bytecode. |
405 // Compile the given MH chain into bytecode. |
268 void compile(TRAPS); |
406 methodHandle compile(TRAPS); |
269 }; |
407 }; |