1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/cpu/x86/vm/methodHandles_x86.hpp Fri May 06 16:33:13 2011 -0700 1.3 @@ -0,0 +1,292 @@ 1.4 +/* 1.5 + * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +// Platform-specific definitions for method handles. 1.29 +// These definitions are inlined into class MethodHandles. 1.30 + 1.31 +public: 1.32 + 1.33 +// The stack just after the recursive call from a ricochet frame 1.34 +// looks something like this. Offsets are marked in words, not bytes. 1.35 +// rsi (r13 on LP64) is part of the interpreter calling sequence 1.36 +// which tells the callee where is my real rsp (for frame walking). 1.37 +// (...lower memory addresses) 1.38 +// rsp: [ return pc ] always the global RicochetBlob::bounce_addr 1.39 +// rsp+1: [ recursive arg N ] 1.40 +// rsp+2: [ recursive arg N-1 ] 1.41 +// ... 1.42 +// rsp+N: [ recursive arg 1 ] 1.43 +// rsp+N+1: [ recursive method handle ] 1.44 +// ... 1.45 +// rbp-6: [ cleanup continuation pc ] <-- (struct RicochetFrame) 1.46 +// rbp-5: [ saved target MH ] the MH we will call on the saved args 1.47 +// rbp-4: [ saved args layout oop ] an int[] array which describes argument layout 1.48 +// rbp-3: [ saved args pointer ] address of transformed adapter arg M (slot 0) 1.49 +// rbp-2: [ conversion ] information about how the return value is used 1.50 +// rbp-1: [ exact sender sp ] exact TOS (rsi/r13) of original sender frame 1.51 +// rbp+0: [ saved sender fp ] (for original sender of AMH) 1.52 +// rbp+1: [ saved sender pc ] (back to original sender of AMH) 1.53 +// rbp+2: [ transformed adapter arg M ] <-- (extended TOS of original sender) 1.54 +// rbp+3: [ transformed adapter arg M-1] 1.55 +// ... 1.56 +// rbp+M+1: [ transformed adapter arg 1 ] 1.57 +// rbp+M+2: [ padding ] <-- (rbp + saved args base offset) 1.58 +// ... [ optional padding] 1.59 +// (higher memory addresses...) 1.60 +// 1.61 +// The arguments originally passed by the original sender 1.62 +// are lost, and arbitrary amounts of stack motion might have 1.63 +// happened due to argument transformation. 1.64 +// (This is done by C2I/I2C adapters and non-direct method handles.) 1.65 +// This is why there is an unpredictable amount of memory between 1.66 +// the extended and exact TOS of the sender. 1.67 +// The ricochet adapter itself will also (in general) perform 1.68 +// transformations before the recursive call. 1.69 +// 1.70 +// The transformed and saved arguments, immediately above the saved 1.71 +// return PC, are a well-formed method handle invocation ready to execute. 1.72 +// When the GC needs to walk the stack, these arguments are described 1.73 +// via the saved arg types oop, an int[] array with a private format. 1.74 +// This array is derived from the type of the transformed adapter 1.75 +// method handle, which also sits at the base of the saved argument 1.76 +// bundle. Since the GC may not be able to fish out the int[] 1.77 +// array, so it is pushed explicitly on the stack. This may be 1.78 +// an unnecessary expense. 1.79 +// 1.80 +// The following register conventions are significant at this point: 1.81 +// rsp the thread stack, as always; preserved by caller 1.82 +// rsi/r13 exact TOS of recursive frame (contents of [rbp-2]) 1.83 +// rcx recursive method handle (contents of [rsp+N+1]) 1.84 +// rbp preserved by caller (not used by caller) 1.85 +// Unless otherwise specified, all registers can be blown by the call. 1.86 +// 1.87 +// If this frame must be walked, the transformed adapter arguments 1.88 +// will be found with the help of the saved arguments descriptor. 1.89 +// 1.90 +// Therefore, the descriptor must match the referenced arguments. 1.91 +// The arguments must be followed by at least one word of padding, 1.92 +// which will be necessary to complete the final method handle call. 1.93 +// That word is not treated as holding an oop. Neither is the word 1.94 +// 1.95 +// The word pointed to by the return argument pointer is not 1.96 +// treated as an oop, even if points to a saved argument. 1.97 +// This allows the saved argument list to have a "hole" in it 1.98 +// to receive an oop from the recursive call. 1.99 +// (The hole might temporarily contain RETURN_VALUE_PLACEHOLDER.) 1.100 +// 1.101 +// When the recursive callee returns, RicochetBlob::bounce_addr will 1.102 +// immediately jump to the continuation stored in the RF. 1.103 +// This continuation will merge the recursive return value 1.104 +// into the saved argument list. At that point, the original 1.105 +// rsi, rbp, and rsp will be reloaded, the ricochet frame will 1.106 +// disappear, and the final target of the adapter method handle 1.107 +// will be invoked on the transformed argument list. 1.108 + 1.109 +class RicochetFrame { 1.110 + friend class MethodHandles; 1.111 + 1.112 + private: 1.113 + intptr_t* _continuation; // what to do when control gets back here 1.114 + oopDesc* _saved_target; // target method handle to invoke on saved_args 1.115 + oopDesc* _saved_args_layout; // caching point for MethodTypeForm.vmlayout cookie 1.116 + intptr_t* _saved_args_base; // base of pushed arguments (slot 0, arg N) (-3) 1.117 + intptr_t _conversion; // misc. information from original AdapterMethodHandle (-2) 1.118 + intptr_t* _exact_sender_sp; // parallel to interpreter_frame_sender_sp (-1) 1.119 + intptr_t* _sender_link; // *must* coincide with frame::link_offset (0) 1.120 + address _sender_pc; // *must* coincide with frame::return_addr_offset (1) 1.121 + 1.122 + public: 1.123 + intptr_t* continuation() const { return _continuation; } 1.124 + oop saved_target() const { return _saved_target; } 1.125 + oop saved_args_layout() const { return _saved_args_layout; } 1.126 + intptr_t* saved_args_base() const { return _saved_args_base; } 1.127 + intptr_t conversion() const { return _conversion; } 1.128 + intptr_t* exact_sender_sp() const { return _exact_sender_sp; } 1.129 + intptr_t* sender_link() const { return _sender_link; } 1.130 + address sender_pc() const { return _sender_pc; } 1.131 + 1.132 + intptr_t* extended_sender_sp() const { return saved_args_base(); } 1.133 + 1.134 + intptr_t return_value_slot_number() const { 1.135 + return adapter_conversion_vminfo(conversion()); 1.136 + } 1.137 + BasicType return_value_type() const { 1.138 + return adapter_conversion_dest_type(conversion()); 1.139 + } 1.140 + bool has_return_value_slot() const { 1.141 + return return_value_type() != T_VOID; 1.142 + } 1.143 + intptr_t* return_value_slot_addr() const { 1.144 + assert(has_return_value_slot(), ""); 1.145 + return saved_arg_slot_addr(return_value_slot_number()); 1.146 + } 1.147 + intptr_t* saved_target_slot_addr() const { 1.148 + return saved_arg_slot_addr(saved_args_length()); 1.149 + } 1.150 + intptr_t* saved_arg_slot_addr(int slot) const { 1.151 + assert(slot >= 0, ""); 1.152 + return (intptr_t*)( (address)saved_args_base() + (slot * Interpreter::stackElementSize) ); 1.153 + } 1.154 + 1.155 + jint saved_args_length() const; 1.156 + jint saved_arg_offset(int arg) const; 1.157 + 1.158 + // GC interface 1.159 + oop* saved_target_addr() { return (oop*)&_saved_target; } 1.160 + oop* saved_args_layout_addr() { return (oop*)&_saved_args_layout; } 1.161 + 1.162 + oop compute_saved_args_layout(bool read_cache, bool write_cache); 1.163 + 1.164 + // Compiler/assembler interface. 1.165 + static int continuation_offset_in_bytes() { return offset_of(RicochetFrame, _continuation); } 1.166 + static int saved_target_offset_in_bytes() { return offset_of(RicochetFrame, _saved_target); } 1.167 + static int saved_args_layout_offset_in_bytes(){ return offset_of(RicochetFrame, _saved_args_layout); } 1.168 + static int saved_args_base_offset_in_bytes() { return offset_of(RicochetFrame, _saved_args_base); } 1.169 + static int conversion_offset_in_bytes() { return offset_of(RicochetFrame, _conversion); } 1.170 + static int exact_sender_sp_offset_in_bytes() { return offset_of(RicochetFrame, _exact_sender_sp); } 1.171 + static int sender_link_offset_in_bytes() { return offset_of(RicochetFrame, _sender_link); } 1.172 + static int sender_pc_offset_in_bytes() { return offset_of(RicochetFrame, _sender_pc); } 1.173 + 1.174 + // This value is not used for much, but it apparently must be nonzero. 1.175 + static int frame_size_in_bytes() { return sender_link_offset_in_bytes(); } 1.176 + 1.177 +#ifdef ASSERT 1.178 + // The magic number is supposed to help find ricochet frames within the bytes of stack dumps. 1.179 + enum { MAGIC_NUMBER_1 = 0xFEED03E, MAGIC_NUMBER_2 = 0xBEEF03E }; 1.180 + static int magic_number_1_offset_in_bytes() { return -wordSize; } 1.181 + static int magic_number_2_offset_in_bytes() { return sizeof(RicochetFrame); } 1.182 + intptr_t magic_number_1() const { return *(intptr_t*)((address)this + magic_number_1_offset_in_bytes()); }; 1.183 + intptr_t magic_number_2() const { return *(intptr_t*)((address)this + magic_number_2_offset_in_bytes()); }; 1.184 +#endif //ASSERT 1.185 + 1.186 + enum { RETURN_VALUE_PLACEHOLDER = (NOT_DEBUG(0) DEBUG_ONLY(42)) }; 1.187 + 1.188 + static void verify_offsets() NOT_DEBUG_RETURN; 1.189 + void verify() const NOT_DEBUG_RETURN; // check for MAGIC_NUMBER, etc. 1.190 + void zap_arguments() NOT_DEBUG_RETURN; 1.191 + 1.192 + static void generate_ricochet_blob(MacroAssembler* _masm, 1.193 + // output params: 1.194 + int* frame_size_in_words, int* bounce_offset, int* exception_offset); 1.195 + 1.196 + static void enter_ricochet_frame(MacroAssembler* _masm, 1.197 + Register rcx_recv, 1.198 + Register rax_argv, 1.199 + address return_handler, 1.200 + Register rbx_temp); 1.201 + static void leave_ricochet_frame(MacroAssembler* _masm, 1.202 + Register rcx_recv, 1.203 + Register new_sp_reg, 1.204 + Register sender_pc_reg); 1.205 + 1.206 + static Address frame_address(int offset = 0) { 1.207 + // The RicochetFrame is found by subtracting a constant offset from rbp. 1.208 + return Address(rbp, - sender_link_offset_in_bytes() + offset); 1.209 + } 1.210 + 1.211 + static RicochetFrame* from_frame(const frame& fr) { 1.212 + address bp = (address) fr.fp(); 1.213 + RicochetFrame* rf = (RicochetFrame*)(bp - sender_link_offset_in_bytes()); 1.214 + rf->verify(); 1.215 + return rf; 1.216 + } 1.217 + 1.218 + static void verify_clean(MacroAssembler* _masm) NOT_DEBUG_RETURN; 1.219 +}; 1.220 + 1.221 +// Additional helper methods for MethodHandles code generation: 1.222 +public: 1.223 + static void load_klass_from_Class(MacroAssembler* _masm, Register klass_reg); 1.224 + static void load_conversion_vminfo(MacroAssembler* _masm, Register reg, Address conversion_field_addr); 1.225 + static void load_conversion_dest_type(MacroAssembler* _masm, Register reg, Address conversion_field_addr); 1.226 + 1.227 + static void load_stack_move(MacroAssembler* _masm, 1.228 + Register rdi_stack_move, 1.229 + Register rcx_amh, 1.230 + bool might_be_negative); 1.231 + 1.232 + static void insert_arg_slots(MacroAssembler* _masm, 1.233 + RegisterOrConstant arg_slots, 1.234 + Register rax_argslot, 1.235 + Register rbx_temp, Register rdx_temp); 1.236 + 1.237 + static void remove_arg_slots(MacroAssembler* _masm, 1.238 + RegisterOrConstant arg_slots, 1.239 + Register rax_argslot, 1.240 + Register rbx_temp, Register rdx_temp); 1.241 + 1.242 + static void push_arg_slots(MacroAssembler* _masm, 1.243 + Register rax_argslot, 1.244 + RegisterOrConstant slot_count, 1.245 + int skip_words_count, 1.246 + Register rbx_temp, Register rdx_temp); 1.247 + 1.248 + static void move_arg_slots_up(MacroAssembler* _masm, 1.249 + Register rbx_bottom, // invariant 1.250 + Address top_addr, // can use rax_temp 1.251 + RegisterOrConstant positive_distance_in_slots, 1.252 + Register rax_temp, Register rdx_temp); 1.253 + 1.254 + static void move_arg_slots_down(MacroAssembler* _masm, 1.255 + Address bottom_addr, // can use rax_temp 1.256 + Register rbx_top, // invariant 1.257 + RegisterOrConstant negative_distance_in_slots, 1.258 + Register rax_temp, Register rdx_temp); 1.259 + 1.260 + static void move_typed_arg(MacroAssembler* _masm, 1.261 + BasicType type, bool is_element, 1.262 + Address slot_dest, Address value_src, 1.263 + Register rbx_temp, Register rdx_temp); 1.264 + 1.265 + static void move_return_value(MacroAssembler* _masm, BasicType type, 1.266 + Address return_slot); 1.267 + 1.268 + static void verify_argslot(MacroAssembler* _masm, Register argslot_reg, 1.269 + const char* error_message) NOT_DEBUG_RETURN; 1.270 + 1.271 + static void verify_argslots(MacroAssembler* _masm, 1.272 + RegisterOrConstant argslot_count, 1.273 + Register argslot_reg, 1.274 + bool negate_argslot, 1.275 + const char* error_message) NOT_DEBUG_RETURN; 1.276 + 1.277 + static void verify_stack_move(MacroAssembler* _masm, 1.278 + RegisterOrConstant arg_slots, 1.279 + int direction) NOT_DEBUG_RETURN; 1.280 + 1.281 + static void verify_klass(MacroAssembler* _masm, 1.282 + Register obj, KlassHandle klass, 1.283 + const char* error_message = "wrong klass") NOT_DEBUG_RETURN; 1.284 + 1.285 + static void verify_method_handle(MacroAssembler* _masm, Register mh_reg) { 1.286 + verify_klass(_masm, mh_reg, SystemDictionaryHandles::MethodHandle_klass(), 1.287 + "reference is a MH"); 1.288 + } 1.289 + 1.290 + static void trace_method_handle(MacroAssembler* _masm, const char* adaptername) PRODUCT_RETURN; 1.291 + 1.292 + static Register saved_last_sp_register() { 1.293 + // Should be in sharedRuntime, not here. 1.294 + return LP64_ONLY(r13) NOT_LP64(rsi); 1.295 + }