Print this page
rev 1080 : [mq]: meth.walker.patch
rev 1083 : [mq]: indy.compiler.inline.patch
Split |
Close |
Expand all |
Collapse all |
--- old/src/share/vm/prims/methodHandleWalk.hpp
+++ new/src/share/vm/prims/methodHandleWalk.hpp
1 1 /*
2 2 * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 4 *
5 5 * This code is free software; you can redistribute it and/or modify it
6 6 * under the terms of the GNU General Public License version 2 only, as
7 7 * published by the Free Software Foundation.
8 8 *
9 9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 12 * version 2 for more details (a copy is included in the LICENSE file that
13 13 * accompanied this code).
14 14 *
15 15 * You should have received a copy of the GNU General Public License version
16 16 * 2 along with this work; if not, write to the Free Software Foundation,
17 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 18 *
19 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 21 * have any questions.
22 22 *
23 23 */
24 24
25 25 // Low-level parser for method handle chains.
26 26 class MethodHandleChain : StackObj {
27 27 public:
28 28 typedef MethodHandles::EntryKind EntryKind;
29 29
30 30 private:
31 31 Handle _root; // original target
32 32 Handle _method_handle; // current target
33 33 bool _is_last; // final guy in chain
34 34 bool _is_bound; // has a bound argument
35 35 BasicType _arg_type; // if is_bound, the bound argument type
36 36 int _arg_slot; // if is_bound or is_adapter, affected argument slot
37 37 jint _conversion; // conversion field of AMH or -1
38 38 methodHandle _last_method; // if is_last, which method we target
39 39 Bytecodes::Code _last_invoke; // if is_last, type of invoke
40 40 const char* _lose_message; // saved argument to lose()
41 41
42 42 void set_method_handle(Handle target, TRAPS);
43 43 void set_last_method(oop target, TRAPS);
44 44 static BasicType compute_bound_arg_type(oop target, methodOop m, int arg_slot, TRAPS);
45 45
46 46 oop MethodHandle_type_oop() { return java_dyn_MethodHandle::type(method_handle_oop()); }
47 47 oop MethodHandle_vmtarget_oop() { return java_dyn_MethodHandle::vmtarget(method_handle_oop()); }
48 48 int MethodHandle_vmslots() { return java_dyn_MethodHandle::vmslots(method_handle_oop()); }
49 49 int DirectMethodHandle_vmindex() { return sun_dyn_DirectMethodHandle::vmindex(method_handle_oop()); }
50 50 oop BoundMethodHandle_argument_oop() { return sun_dyn_BoundMethodHandle::argument(method_handle_oop()); }
51 51 int BoundMethodHandle_vmargslot() { return sun_dyn_BoundMethodHandle::vmargslot(method_handle_oop()); }
52 52 int AdapterMethodHandle_conversion() { return sun_dyn_AdapterMethodHandle::conversion(method_handle_oop()); }
53 53
54 54 public:
55 55 MethodHandleChain(Handle root, TRAPS)
56 56 : _root(root)
57 57 { set_method_handle(root, THREAD); }
58 58
59 59 bool is_adapter() { return _conversion != -1; }
60 60 bool is_bound() { return _is_bound; }
↓ open down ↓ |
60 lines elided |
↑ open up ↑ |
61 61 bool is_last() { return _is_last; }
62 62
63 63 void next(TRAPS) {
64 64 assert(!is_last(), "");
65 65 set_method_handle(MethodHandle_vmtarget_oop(), THREAD);
66 66 }
67 67
68 68 Handle method_handle() { return _method_handle; }
69 69 oop method_handle_oop() { return _method_handle(); }
70 70 oop method_type_oop() { return MethodHandle_type_oop(); }
71 + oop vmtarget_oop() { return MethodHandle_vmtarget_oop(); }
71 72
72 73 jint adapter_conversion() { assert(is_adapter(), ""); return _conversion; }
73 74 int adapter_conversion_op() { return MethodHandles::adapter_conversion_op(adapter_conversion()); }
74 75 BasicType adapter_conversion_src_type()
75 76 { return MethodHandles::adapter_conversion_src_type(adapter_conversion()); }
76 77 BasicType adapter_conversion_dest_type()
77 78 { return MethodHandles::adapter_conversion_dest_type(adapter_conversion()); }
78 79 int adapter_conversion_stack_move()
79 80 { return MethodHandles::adapter_conversion_stack_move(adapter_conversion()); }
80 81 int adapter_conversion_stack_pushes()
81 82 { return adapter_conversion_stack_move() / MethodHandles::stack_move_unit(); }
82 83 int adapter_conversion_vminfo()
83 84 { return MethodHandles::adapter_conversion_vminfo(adapter_conversion()); }
84 85 int adapter_arg_slot() { assert(is_adapter(), ""); return _arg_slot; }
85 86 oop adapter_arg_oop() { assert(is_adapter(), ""); return BoundMethodHandle_argument_oop(); }
86 87
87 88 BasicType bound_arg_type() { assert(is_bound(), ""); return _arg_type; }
88 89 int bound_arg_slot() { assert(is_bound(), ""); return _arg_slot; }
89 90 oop bound_arg_oop() { assert(is_bound(), ""); return BoundMethodHandle_argument_oop(); }
90 91
91 92 methodOop last_method_oop() { assert(is_last(), ""); return _last_method(); }
92 93 Bytecodes::Code last_invoke_code() { assert(is_last(), ""); return _last_invoke; }
93 94
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
94 95 void lose(const char* msg, TRAPS);
95 96 const char* lose_message() { return _lose_message; }
96 97 };
97 98
98 99
99 100 // Structure walker for method handles.
100 101 // Does abstract interpretation on top of low-level parsing.
101 102 // You supply the tokens shuffled by the abstract interpretation.
102 103 class MethodHandleWalker : StackObj {
103 104 public:
104 - struct _ArgToken { }; // dummy struct
105 - typedef _ArgToken* ArgToken;
105 + // Stack values:
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 145 // Abstract interpretation state:
108 146 struct SlotState {
109 147 BasicType _type;
110 148 ArgToken _arg;
111 149 };
112 150 static SlotState make_state(BasicType type, ArgToken arg) {
113 151 SlotState ss;
114 152 ss._type = type; ss._arg = arg;
115 153 return ss;
116 154 }
117 155
118 156 private:
119 157 MethodHandleChain _chain;
158 + bool _for_invokedynamic;
159 + int _local_index;
120 160
121 - GrowableArray<SlotState> _outgoing; // current outgoing parameter slots
161 + GrowableArray<SlotState> _outgoing; // current outgoing parameter slots
122 162 int _outgoing_argc; // # non-empty outgoing slots
123 163
124 164 // Replace a value of type old_type at slot (and maybe slot+1) with the new value.
125 165 // If old_type != T_VOID, remove the old argument at that point.
126 166 // If new_type != T_VOID, insert the new argument at that point.
127 167 // Insert or delete a second empty slot as needed.
128 - void change_argument(BasicType old_type, int slot, BasicType new_type, ArgToken new_arg);
168 + void change_argument(BasicType old_type, int slot, BasicType new_type, const ArgToken& new_arg);
129 169
130 170 SlotState* slot_state(int slot) {
131 171 if (slot < 0 || slot >= _outgoing.length())
132 172 return NULL;
133 173 return _outgoing.adr_at(slot);
134 174 }
135 175 BasicType slot_type(int slot) {
136 176 SlotState* ss = slot_state(slot);
137 177 if (ss == NULL)
138 178 return T_ILLEGAL;
139 179 return ss->_type;
140 180 }
141 181 bool slot_has_argument(int slot) {
142 182 return slot_type(slot) < T_VOID;
143 183 }
144 184
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
145 185 #ifdef ASSERT
146 186 int argument_count_slow();
147 187 #endif
148 188
149 189 // Return a bytecode for converting src to dest, if one exists.
150 190 Bytecodes::Code conversion_code(BasicType src, BasicType dest);
151 191
152 192 void walk_incoming_state(TRAPS);
153 193
154 194 public:
155 - MethodHandleWalker(Handle root, TRAPS)
195 + MethodHandleWalker(Handle root, bool for_invokedynamic, TRAPS)
156 196 : _chain(root, THREAD),
197 + _for_invokedynamic(for_invokedynamic),
157 198 _outgoing(THREAD, 10),
158 199 _outgoing_argc(0)
159 - { }
200 + {
201 + _local_index = for_invokedynamic ? 0 : 1;
202 + }
160 203
161 204 MethodHandleChain& chain() { return _chain; }
162 205
206 + bool for_invokedynamic() const { return _for_invokedynamic; }
207 +
208 + int new_local_index(BasicType bt) {
209 + //int index = _for_invokedynamic ? _local_index : _local_index - 1;
210 + int index = _local_index;
211 + _local_index += type2size[bt];
212 + return index;
213 + }
214 +
215 + int max_locals() const { return _local_index; }
216 +
163 217 // plug-in abstract interpretation steps:
164 218 virtual ArgToken make_parameter( BasicType type, klassOop tk, int argnum, TRAPS ) = 0;
165 219 virtual ArgToken make_prim_constant( BasicType type, jvalue* con, TRAPS ) = 0;
166 220 virtual ArgToken make_oop_constant( oop con, TRAPS ) = 0;
167 - virtual ArgToken make_conversion( BasicType type, klassOop tk, Bytecodes::Code op, ArgToken src, TRAPS ) = 0;
168 - virtual ArgToken make_fetch( BasicType type, klassOop tk, Bytecodes::Code op, ArgToken base, ArgToken offset, TRAPS ) = 0;
221 + virtual ArgToken make_conversion( BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS ) = 0;
222 + virtual ArgToken make_fetch( BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS ) = 0;
169 223 virtual ArgToken make_invoke( methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS ) = 0;
170 224
171 225 // For make_invoke, the methodOop can be NULL if the intrinsic ID
172 226 // is something other than vmIntrinsics::_none.
173 227
174 228 // and in case anyone cares to related the previous actions to the chain:
175 229 virtual void set_method_handle(oop mh) { }
176 230
177 231 void lose(const char* msg, TRAPS) { chain().lose(msg, THREAD); }
178 232 const char* lose_message() { return chain().lose_message(); }
179 233
180 234 ArgToken walk(TRAPS);
181 235 };
182 236
183 237
184 238 // An abstract interpreter for method handle chains.
185 239 // Produces an account of the semantics of a chain, in terms of a static IR.
186 240 // The IR happens to be JVM bytecodes.
187 241 class MethodHandleCompiler : public MethodHandleWalker {
188 242 private:
189 - Thread* _thread;
190 -
191 - struct PrimCon {
192 - BasicType _type;
193 - jvalue _value;
243 + methodHandle _callee;
244 + KlassHandle _rklass; // Return type for casting.
245 + BasicType _rtype;
246 + KlassHandle _target_klass;
247 + Thread* _thread;
248 +
249 + // Fake constant pool entry.
250 + class ConstantValue {
251 + private:
252 + int _tag; // Constant pool tag type.
253 + JavaValue _value;
254 + Handle _handle;
255 +
256 + public:
257 + // Constructor for oop types.
258 + ConstantValue(int tag, Handle con) : _tag(tag), _handle(con) {
259 + assert(tag == JVM_CONSTANT_Utf8 ||
260 + tag == JVM_CONSTANT_Class ||
261 + tag == JVM_CONSTANT_String ||
262 + tag == JVM_CONSTANT_Object, "must be oop type");
263 + }
264 +
265 + // Constructor for oop reference types.
266 + ConstantValue(int tag, int index) : _tag(tag) {
267 + assert(JVM_CONSTANT_Fieldref <= tag && tag <= JVM_CONSTANT_NameAndType, "must be ref type");
268 + _value.set_jint(index);
269 + }
270 + ConstantValue(int tag, int first_index, int second_index) : _tag(tag) {
271 + assert(JVM_CONSTANT_Fieldref <= tag && tag <= JVM_CONSTANT_NameAndType, "must be ref type");
272 + _value.set_jint(first_index << 16 | second_index);
273 + }
274 +
275 + // Constructor for primitive types.
276 + ConstantValue(BasicType bt, jvalue con) {
277 + _value.set_type(bt);
278 + switch (bt) {
279 + case T_INT: _tag = JVM_CONSTANT_Integer; _value.set_jint( con.i); break;
280 + case T_LONG: _tag = JVM_CONSTANT_Long; _value.set_jlong( con.j); break;
281 + case T_FLOAT: _tag = JVM_CONSTANT_Float; _value.set_jfloat( con.f); break;
282 + case T_DOUBLE: _tag = JVM_CONSTANT_Double; _value.set_jdouble(con.d); break;
283 + default: ShouldNotReachHere();
284 + }
285 + }
286 +
287 + int tag() const { return _tag; }
288 + symbolOop symbol_oop() const { return (symbolOop) _handle(); }
289 + klassOop klass_oop() const { return (klassOop) _handle(); }
290 + oop object_oop() const { return _handle(); }
291 + int index() const { return _value.get_jint(); }
292 + int first_index() const { return _value.get_jint() >> 16; }
293 + int second_index() const { return _value.get_jint() & 0x0000FFFF; }
294 +
295 + bool is_primitive() const { return is_java_primitive(_value.get_type()); }
296 + jint get_jint() const { return _value.get_jint(); }
297 + jlong get_jlong() const { return _value.get_jlong(); }
298 + jfloat get_jfloat() const { return _value.get_jfloat(); }
299 + jdouble get_jdouble() const { return _value.get_jdouble(); }
194 300 };
195 301
302 + // Fake constant pool.
303 + GrowableArray<ConstantValue*> _constants;
304 +
196 305 // Accumulated compiler state:
197 - stringStream _bytes;
198 - GrowableArray<Handle> _constant_oops;
199 - GrowableArray<PrimCon*> _constant_prims;
306 + GrowableArray<unsigned char> _bytecode;
307 +
308 + int _cur_stack;
200 309 int _max_stack;
201 310 int _num_params;
202 - int _max_locals;
203 311 int _name_index;
204 312 int _signature_index;
205 313
206 - // Stack values:
207 - enum TokenType {
208 - tt_void,
209 - tt_parameter,
210 - tt_temporary,
211 - tt_constant
212 - };
314 + void stack_push(BasicType bt) {
315 + _cur_stack += type2size[bt];
316 + if (_cur_stack > _max_stack) _max_stack = _cur_stack;
317 + }
318 + void stack_pop(BasicType bt) {
319 + _cur_stack -= type2size[bt];
320 + assert(_cur_stack >= 0, "sanity");
321 + }
322 +
323 + unsigned char* bytecode() const { return _bytecode.adr_at(0); }
324 + int bytecode_length() const { return _bytecode.length(); }
213 325
214 - ArgToken make_stack_value(TokenType tt, BasicType type, int id) {
215 - return ArgToken( ((intptr_t)id << 8) | ((intptr_t)type << 4) | (intptr_t)tt );
326 + // Fake constant pool.
327 + int cpool_oop_put(int tag, Handle con) {
328 + if (con.is_null()) return 0;
329 + ConstantValue* cv = new ConstantValue(tag, con);
330 + return _constants.append(cv);
216 331 }
217 332
218 -public:
333 + int cpool_oop_reference_put(int tag, int first_index, int second_index) {
334 + if (first_index == 0 && second_index == 0) return 0;
335 + assert(first_index != 0 && second_index != 0, "no zero indexes");
336 + ConstantValue* cv = new ConstantValue(tag, first_index, second_index);
337 + return _constants.append(cv);
338 + }
339 +
340 + int cpool_primitive_put(BasicType type, jvalue* con);
341 +
342 + int cpool_int_put(jint value) {
343 + jvalue con; con.i = value;
344 + return cpool_primitive_put(T_INT, &con);
345 + }
346 + int cpool_long_put(jlong value) {
347 + jvalue con; con.j = value;
348 + return cpool_primitive_put(T_LONG, &con);
349 + }
350 + int cpool_float_put(jfloat value) {
351 + jvalue con; con.f = value;
352 + return cpool_primitive_put(T_FLOAT, &con);
353 + }
354 + int cpool_double_put(jdouble value) {
355 + jvalue con; con.d = value;
356 + return cpool_primitive_put(T_DOUBLE, &con);
357 + }
358 +
359 + int cpool_object_put(Handle obj) {
360 + return cpool_oop_put(JVM_CONSTANT_Object, obj);
361 + }
362 + int cpool_symbol_put(symbolOop sym) {
363 + return cpool_oop_put(JVM_CONSTANT_Utf8, sym);
364 + }
365 + int cpool_klass_put(klassOop klass) {
366 + return cpool_oop_put(JVM_CONSTANT_Class, klass);
367 + }
368 + int cpool_methodref_put(int class_index, int name_and_type_index) {
369 + return cpool_oop_reference_put(JVM_CONSTANT_Methodref, class_index, name_and_type_index);
370 + }
371 + int cpool_name_and_type_put(int name_index, int signature_index) {
372 + return cpool_oop_reference_put(JVM_CONSTANT_NameAndType, name_index, signature_index);
373 + }
374 +
375 + void emit_bc(Bytecodes::Code op, int index = 0);
376 + void emit_load(BasicType bt, int index);
377 + void emit_store(BasicType bt, int index);
378 + void emit_load_constant(ArgToken arg);
379 +
219 380 virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) {
220 - return make_stack_value(tt_parameter, type, argnum);
381 + return ArgToken(tt_parameter, type, argnum);
221 382 }
222 383 virtual ArgToken make_oop_constant(oop con, TRAPS) {
223 - return make_stack_value(tt_constant, T_OBJECT, find_oop_constant(con));
384 + Handle h(THREAD, con);
385 + return ArgToken(tt_constant, T_OBJECT, h);
224 386 }
225 387 virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) {
226 - return make_stack_value(tt_constant, type, find_prim_constant(type, con));
388 + return ArgToken(tt_constant, type, *con);
227 389 }
228 - virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken src, TRAPS);
229 - virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken base, ArgToken offset, TRAPS);
390 +
391 + virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS);
392 + virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS);
230 393 virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS);
231 394
232 - int find_oop_constant(oop con);
233 - int find_prim_constant(BasicType type, jvalue* con);
395 + // Get a real constant pool.
396 + constantPoolHandle get_constant_pool(TRAPS) const;
397 +
398 + // Get a real methodOop.
399 + methodHandle get_method_oop(TRAPS) const;
234 400
235 401 public:
236 - MethodHandleCompiler(Handle root, TRAPS)
237 - : MethodHandleWalker(root, THREAD),
238 - _thread(THREAD),
239 - _bytes(50),
240 - _constant_oops(THREAD, 10),
241 - _constant_prims(THREAD, 10),
242 - _max_stack(0), _max_locals(0),
243 - _name_index(0), _signature_index(0)
244 - { }
245 - const char* bytes() { return _bytes.as_string(); }
246 - int constant_length() { return _constant_oops.length(); }
247 - int max_stack() { return _max_stack; }
248 - int max_locals() { return _max_locals; }
249 - int name_index() { return _name_index; }
250 - int signature_index() { return _signature_index; }
251 - symbolHandle name() { return symbolHandle(_thread, (symbolOop)constant_oop_at(_name_index)()); }
252 - symbolHandle signature() { return symbolHandle(_thread, (symbolOop)constant_oop_at(_signature_index)()); }
253 -
254 - bool constant_is_oop_at(int i) {
255 - return (_constant_prims.at(i) == NULL);
256 - }
257 - Handle constant_oop_at(int i) {
258 - assert(constant_is_oop_at(i), "");
259 - return _constant_oops.at(i);
260 - }
261 - PrimCon* constant_prim_at(int i) {
262 - assert(!constant_is_oop_at(i), "");
263 - return _constant_prims.at(i);
264 - }
402 + MethodHandleCompiler(Handle root, methodHandle call_method, bool for_invokedynamic, TRAPS);
265 403
266 404 // Compile the given MH chain into bytecode.
267 - void compile(TRAPS);
405 + methodHandle compile(TRAPS);
268 406 };
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX