Mercurial > hg > truffle
comparison src/share/vm/prims/methodHandleWalk.hpp @ 1138:dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
Summary: C2 needs some additional optimizations to be able to handle MethodHandle invokes and invokedynamic instructions at the best performance.
Reviewed-by: kvn, never
author | twisti |
---|---|
date | Tue, 05 Jan 2010 15:21:25 +0100 |
parents | aa62b9388fce |
children | cd37471eaecc |
comparison
equal
deleted
inserted
replaced
1137:97125851f396 | 1138:dd57230ba8fe |
---|---|
66 } | 66 } |
67 | 67 |
68 Handle method_handle() { return _method_handle; } | 68 Handle method_handle() { return _method_handle; } |
69 oop method_handle_oop() { return _method_handle(); } | 69 oop method_handle_oop() { return _method_handle(); } |
70 oop method_type_oop() { return MethodHandle_type_oop(); } | 70 oop method_type_oop() { return MethodHandle_type_oop(); } |
71 oop vmtarget_oop() { return MethodHandle_vmtarget_oop(); } | |
71 | 72 |
72 jint adapter_conversion() { assert(is_adapter(), ""); return _conversion; } | 73 jint adapter_conversion() { assert(is_adapter(), ""); return _conversion; } |
73 int adapter_conversion_op() { return MethodHandles::adapter_conversion_op(adapter_conversion()); } | 74 int adapter_conversion_op() { return MethodHandles::adapter_conversion_op(adapter_conversion()); } |
74 BasicType adapter_conversion_src_type() | 75 BasicType adapter_conversion_src_type() |
75 { return MethodHandles::adapter_conversion_src_type(adapter_conversion()); } | 76 { return MethodHandles::adapter_conversion_src_type(adapter_conversion()); } |
99 // Structure walker for method handles. | 100 // Structure walker for method handles. |
100 // Does abstract interpretation on top of low-level parsing. | 101 // Does abstract interpretation on top of low-level parsing. |
101 // You supply the tokens shuffled by the abstract interpretation. | 102 // You supply the tokens shuffled by the abstract interpretation. |
102 class MethodHandleWalker : StackObj { | 103 class MethodHandleWalker : StackObj { |
103 public: | 104 public: |
104 struct _ArgToken { }; // dummy struct | 105 // Stack values: |
105 typedef _ArgToken* ArgToken; | 106 enum TokenType { |
107 tt_void, | |
108 tt_parameter, | |
109 tt_temporary, | |
110 tt_constant, | |
111 tt_illegal | |
112 }; | |
113 | |
114 // Argument token: | |
115 class ArgToken { | |
116 private: | |
117 TokenType _tt; | |
118 BasicType _bt; | |
119 jvalue _value; | |
120 Handle _handle; | |
121 | |
122 public: | |
123 ArgToken(TokenType tt = tt_illegal) : _tt(tt) {} | |
124 ArgToken(TokenType tt, BasicType bt, jvalue value) : _tt(tt), _bt(bt), _value(value) {} | |
125 | |
126 ArgToken(TokenType tt, BasicType bt, int index) : _tt(tt), _bt(bt) { | |
127 _value.i = index; | |
128 } | |
129 | |
130 ArgToken(TokenType tt, BasicType bt, Handle value) : _tt(tt), _bt(bt) { | |
131 _handle = value; | |
132 } | |
133 | |
134 TokenType token_type() const { return _tt; } | |
135 BasicType basic_type() const { return _bt; } | |
136 int index() const { return _value.i; } | |
137 Handle object() const { return _handle; } | |
138 | |
139 jint get_jint() const { return _value.i; } | |
140 jlong get_jlong() const { return _value.j; } | |
141 jfloat get_jfloat() const { return _value.f; } | |
142 jdouble get_jdouble() const { return _value.d; } | |
143 }; | |
106 | 144 |
107 // Abstract interpretation state: | 145 // Abstract interpretation state: |
108 struct SlotState { | 146 struct SlotState { |
109 BasicType _type; | 147 BasicType _type; |
110 ArgToken _arg; | 148 ArgToken _arg; |
116 return ss; | 154 return ss; |
117 } | 155 } |
118 | 156 |
119 private: | 157 private: |
120 MethodHandleChain _chain; | 158 MethodHandleChain _chain; |
121 | 159 bool _for_invokedynamic; |
122 GrowableArray<SlotState> _outgoing; // current outgoing parameter slots | 160 int _local_index; |
161 | |
162 GrowableArray<SlotState> _outgoing; // current outgoing parameter slots | |
123 int _outgoing_argc; // # non-empty outgoing slots | 163 int _outgoing_argc; // # non-empty outgoing slots |
124 | 164 |
125 // Replace a value of type old_type at slot (and maybe slot+1) with the new value. | 165 // Replace a value of type old_type at slot (and maybe slot+1) with the new value. |
126 // If old_type != T_VOID, remove the old argument at that point. | 166 // If old_type != T_VOID, remove the old argument at that point. |
127 // If new_type != T_VOID, insert the new argument at that point. | 167 // If new_type != T_VOID, insert the new argument at that point. |
128 // Insert or delete a second empty slot as needed. | 168 // Insert or delete a second empty slot as needed. |
129 void change_argument(BasicType old_type, int slot, BasicType new_type, ArgToken new_arg); | 169 void change_argument(BasicType old_type, int slot, BasicType new_type, const ArgToken& new_arg); |
130 | 170 |
131 SlotState* slot_state(int slot) { | 171 SlotState* slot_state(int slot) { |
132 if (slot < 0 || slot >= _outgoing.length()) | 172 if (slot < 0 || slot >= _outgoing.length()) |
133 return NULL; | 173 return NULL; |
134 return _outgoing.adr_at(slot); | 174 return _outgoing.adr_at(slot); |
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 }; |