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