Mon, 13 Feb 2012 02:29:22 -0800
7141329: Strange values of stack_size in -XX:+TraceMethodHandles output
Reviewed-by: kvn, never
never@2895 | 1 | /* |
bdelsart@3445 | 2 | * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. |
never@2895 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
never@2895 | 4 | * |
never@2895 | 5 | * This code is free software; you can redistribute it and/or modify it |
never@2895 | 6 | * under the terms of the GNU General Public License version 2 only, as |
never@2895 | 7 | * published by the Free Software Foundation. |
never@2895 | 8 | * |
never@2895 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
never@2895 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
never@2895 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
never@2895 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
never@2895 | 13 | * accompanied this code). |
never@2895 | 14 | * |
never@2895 | 15 | * You should have received a copy of the GNU General Public License version |
never@2895 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
never@2895 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
never@2895 | 18 | * |
never@2895 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
never@2895 | 20 | * or visit www.oracle.com if you need additional information or have any |
never@2895 | 21 | * questions. |
never@2895 | 22 | * |
never@2895 | 23 | */ |
never@2895 | 24 | |
never@2895 | 25 | // Platform-specific definitions for method handles. |
never@2895 | 26 | // These definitions are inlined into class MethodHandles. |
never@2895 | 27 | |
never@2950 | 28 | // Adapters |
never@2950 | 29 | enum /* platform_dependent_constants */ { |
never@3314 | 30 | adapter_code_size = NOT_LP64(16000 DEBUG_ONLY(+ 15000)) LP64_ONLY(32000 DEBUG_ONLY(+ 120000)) |
never@2950 | 31 | }; |
never@2950 | 32 | |
never@2895 | 33 | public: |
never@2895 | 34 | |
never@2895 | 35 | // The stack just after the recursive call from a ricochet frame |
never@2895 | 36 | // looks something like this. Offsets are marked in words, not bytes. |
never@2895 | 37 | // rsi (r13 on LP64) is part of the interpreter calling sequence |
never@2895 | 38 | // which tells the callee where is my real rsp (for frame walking). |
never@2895 | 39 | // (...lower memory addresses) |
never@2895 | 40 | // rsp: [ return pc ] always the global RicochetBlob::bounce_addr |
never@2895 | 41 | // rsp+1: [ recursive arg N ] |
never@2895 | 42 | // rsp+2: [ recursive arg N-1 ] |
never@2895 | 43 | // ... |
never@2895 | 44 | // rsp+N: [ recursive arg 1 ] |
never@2895 | 45 | // rsp+N+1: [ recursive method handle ] |
never@2895 | 46 | // ... |
never@2895 | 47 | // rbp-6: [ cleanup continuation pc ] <-- (struct RicochetFrame) |
never@2895 | 48 | // rbp-5: [ saved target MH ] the MH we will call on the saved args |
never@2895 | 49 | // rbp-4: [ saved args layout oop ] an int[] array which describes argument layout |
never@2895 | 50 | // rbp-3: [ saved args pointer ] address of transformed adapter arg M (slot 0) |
never@2895 | 51 | // rbp-2: [ conversion ] information about how the return value is used |
never@2895 | 52 | // rbp-1: [ exact sender sp ] exact TOS (rsi/r13) of original sender frame |
never@2895 | 53 | // rbp+0: [ saved sender fp ] (for original sender of AMH) |
never@2895 | 54 | // rbp+1: [ saved sender pc ] (back to original sender of AMH) |
never@2895 | 55 | // rbp+2: [ transformed adapter arg M ] <-- (extended TOS of original sender) |
never@2895 | 56 | // rbp+3: [ transformed adapter arg M-1] |
never@2895 | 57 | // ... |
never@2895 | 58 | // rbp+M+1: [ transformed adapter arg 1 ] |
never@2895 | 59 | // rbp+M+2: [ padding ] <-- (rbp + saved args base offset) |
never@2895 | 60 | // ... [ optional padding] |
never@2895 | 61 | // (higher memory addresses...) |
never@2895 | 62 | // |
never@2895 | 63 | // The arguments originally passed by the original sender |
never@2895 | 64 | // are lost, and arbitrary amounts of stack motion might have |
never@2895 | 65 | // happened due to argument transformation. |
never@2895 | 66 | // (This is done by C2I/I2C adapters and non-direct method handles.) |
never@2895 | 67 | // This is why there is an unpredictable amount of memory between |
never@2895 | 68 | // the extended and exact TOS of the sender. |
never@2895 | 69 | // The ricochet adapter itself will also (in general) perform |
never@2895 | 70 | // transformations before the recursive call. |
never@2895 | 71 | // |
never@2895 | 72 | // The transformed and saved arguments, immediately above the saved |
never@2895 | 73 | // return PC, are a well-formed method handle invocation ready to execute. |
never@2895 | 74 | // When the GC needs to walk the stack, these arguments are described |
never@2895 | 75 | // via the saved arg types oop, an int[] array with a private format. |
never@2895 | 76 | // This array is derived from the type of the transformed adapter |
never@2895 | 77 | // method handle, which also sits at the base of the saved argument |
never@2895 | 78 | // bundle. Since the GC may not be able to fish out the int[] |
never@2895 | 79 | // array, so it is pushed explicitly on the stack. This may be |
never@2895 | 80 | // an unnecessary expense. |
never@2895 | 81 | // |
never@2895 | 82 | // The following register conventions are significant at this point: |
never@2895 | 83 | // rsp the thread stack, as always; preserved by caller |
never@2895 | 84 | // rsi/r13 exact TOS of recursive frame (contents of [rbp-2]) |
never@2895 | 85 | // rcx recursive method handle (contents of [rsp+N+1]) |
never@2895 | 86 | // rbp preserved by caller (not used by caller) |
never@2895 | 87 | // Unless otherwise specified, all registers can be blown by the call. |
never@2895 | 88 | // |
never@2895 | 89 | // If this frame must be walked, the transformed adapter arguments |
never@2895 | 90 | // will be found with the help of the saved arguments descriptor. |
never@2895 | 91 | // |
never@2895 | 92 | // Therefore, the descriptor must match the referenced arguments. |
never@2895 | 93 | // The arguments must be followed by at least one word of padding, |
never@2895 | 94 | // which will be necessary to complete the final method handle call. |
never@2895 | 95 | // That word is not treated as holding an oop. Neither is the word |
never@2895 | 96 | // |
never@2895 | 97 | // The word pointed to by the return argument pointer is not |
never@2895 | 98 | // treated as an oop, even if points to a saved argument. |
never@2895 | 99 | // This allows the saved argument list to have a "hole" in it |
never@2895 | 100 | // to receive an oop from the recursive call. |
never@2895 | 101 | // (The hole might temporarily contain RETURN_VALUE_PLACEHOLDER.) |
never@2895 | 102 | // |
never@2895 | 103 | // When the recursive callee returns, RicochetBlob::bounce_addr will |
never@2895 | 104 | // immediately jump to the continuation stored in the RF. |
never@2895 | 105 | // This continuation will merge the recursive return value |
never@2895 | 106 | // into the saved argument list. At that point, the original |
never@2895 | 107 | // rsi, rbp, and rsp will be reloaded, the ricochet frame will |
never@2895 | 108 | // disappear, and the final target of the adapter method handle |
never@2895 | 109 | // will be invoked on the transformed argument list. |
never@2895 | 110 | |
never@2895 | 111 | class RicochetFrame { |
never@2895 | 112 | friend class MethodHandles; |
never@3108 | 113 | friend class VMStructs; |
never@2895 | 114 | |
never@2895 | 115 | private: |
never@2895 | 116 | intptr_t* _continuation; // what to do when control gets back here |
never@2895 | 117 | oopDesc* _saved_target; // target method handle to invoke on saved_args |
never@2895 | 118 | oopDesc* _saved_args_layout; // caching point for MethodTypeForm.vmlayout cookie |
never@2895 | 119 | intptr_t* _saved_args_base; // base of pushed arguments (slot 0, arg N) (-3) |
never@2895 | 120 | intptr_t _conversion; // misc. information from original AdapterMethodHandle (-2) |
never@2895 | 121 | intptr_t* _exact_sender_sp; // parallel to interpreter_frame_sender_sp (-1) |
never@2895 | 122 | intptr_t* _sender_link; // *must* coincide with frame::link_offset (0) |
never@2895 | 123 | address _sender_pc; // *must* coincide with frame::return_addr_offset (1) |
never@2895 | 124 | |
never@2895 | 125 | public: |
never@2895 | 126 | intptr_t* continuation() const { return _continuation; } |
never@2895 | 127 | oop saved_target() const { return _saved_target; } |
never@2895 | 128 | oop saved_args_layout() const { return _saved_args_layout; } |
never@2895 | 129 | intptr_t* saved_args_base() const { return _saved_args_base; } |
never@2895 | 130 | intptr_t conversion() const { return _conversion; } |
never@2895 | 131 | intptr_t* exact_sender_sp() const { return _exact_sender_sp; } |
never@2895 | 132 | intptr_t* sender_link() const { return _sender_link; } |
never@2895 | 133 | address sender_pc() const { return _sender_pc; } |
never@2895 | 134 | |
twisti@3196 | 135 | intptr_t* extended_sender_sp() const { |
twisti@3196 | 136 | // The extended sender SP is above the current RicochetFrame. |
twisti@3196 | 137 | return (intptr_t*) (((address) this) + sizeof(RicochetFrame)); |
twisti@3196 | 138 | } |
never@2895 | 139 | |
never@2895 | 140 | intptr_t return_value_slot_number() const { |
never@2895 | 141 | return adapter_conversion_vminfo(conversion()); |
never@2895 | 142 | } |
never@2895 | 143 | BasicType return_value_type() const { |
never@2895 | 144 | return adapter_conversion_dest_type(conversion()); |
never@2895 | 145 | } |
never@2895 | 146 | bool has_return_value_slot() const { |
never@2895 | 147 | return return_value_type() != T_VOID; |
never@2895 | 148 | } |
never@2895 | 149 | intptr_t* return_value_slot_addr() const { |
never@2895 | 150 | assert(has_return_value_slot(), ""); |
never@2895 | 151 | return saved_arg_slot_addr(return_value_slot_number()); |
never@2895 | 152 | } |
never@2895 | 153 | intptr_t* saved_target_slot_addr() const { |
never@2895 | 154 | return saved_arg_slot_addr(saved_args_length()); |
never@2895 | 155 | } |
never@2895 | 156 | intptr_t* saved_arg_slot_addr(int slot) const { |
never@2895 | 157 | assert(slot >= 0, ""); |
never@2895 | 158 | return (intptr_t*)( (address)saved_args_base() + (slot * Interpreter::stackElementSize) ); |
never@2895 | 159 | } |
never@2895 | 160 | |
never@2895 | 161 | jint saved_args_length() const; |
never@2895 | 162 | jint saved_arg_offset(int arg) const; |
never@2895 | 163 | |
never@2895 | 164 | // GC interface |
never@2895 | 165 | oop* saved_target_addr() { return (oop*)&_saved_target; } |
never@2895 | 166 | oop* saved_args_layout_addr() { return (oop*)&_saved_args_layout; } |
never@2895 | 167 | |
never@2895 | 168 | oop compute_saved_args_layout(bool read_cache, bool write_cache); |
never@2895 | 169 | |
never@2895 | 170 | // Compiler/assembler interface. |
never@2895 | 171 | static int continuation_offset_in_bytes() { return offset_of(RicochetFrame, _continuation); } |
never@2895 | 172 | static int saved_target_offset_in_bytes() { return offset_of(RicochetFrame, _saved_target); } |
never@2895 | 173 | static int saved_args_layout_offset_in_bytes(){ return offset_of(RicochetFrame, _saved_args_layout); } |
never@2895 | 174 | static int saved_args_base_offset_in_bytes() { return offset_of(RicochetFrame, _saved_args_base); } |
never@2895 | 175 | static int conversion_offset_in_bytes() { return offset_of(RicochetFrame, _conversion); } |
never@2895 | 176 | static int exact_sender_sp_offset_in_bytes() { return offset_of(RicochetFrame, _exact_sender_sp); } |
never@2895 | 177 | static int sender_link_offset_in_bytes() { return offset_of(RicochetFrame, _sender_link); } |
never@2895 | 178 | static int sender_pc_offset_in_bytes() { return offset_of(RicochetFrame, _sender_pc); } |
never@2895 | 179 | |
never@2895 | 180 | // This value is not used for much, but it apparently must be nonzero. |
never@2895 | 181 | static int frame_size_in_bytes() { return sender_link_offset_in_bytes(); } |
never@2895 | 182 | |
never@2895 | 183 | #ifdef ASSERT |
never@2895 | 184 | // The magic number is supposed to help find ricochet frames within the bytes of stack dumps. |
never@2895 | 185 | enum { MAGIC_NUMBER_1 = 0xFEED03E, MAGIC_NUMBER_2 = 0xBEEF03E }; |
never@2895 | 186 | static int magic_number_1_offset_in_bytes() { return -wordSize; } |
never@2895 | 187 | static int magic_number_2_offset_in_bytes() { return sizeof(RicochetFrame); } |
never@2895 | 188 | intptr_t magic_number_1() const { return *(intptr_t*)((address)this + magic_number_1_offset_in_bytes()); }; |
never@2895 | 189 | intptr_t magic_number_2() const { return *(intptr_t*)((address)this + magic_number_2_offset_in_bytes()); }; |
never@2895 | 190 | #endif //ASSERT |
never@2895 | 191 | |
never@2895 | 192 | enum { RETURN_VALUE_PLACEHOLDER = (NOT_DEBUG(0) DEBUG_ONLY(42)) }; |
never@2895 | 193 | |
never@2895 | 194 | static void verify_offsets() NOT_DEBUG_RETURN; |
never@2895 | 195 | void verify() const NOT_DEBUG_RETURN; // check for MAGIC_NUMBER, etc. |
never@2895 | 196 | void zap_arguments() NOT_DEBUG_RETURN; |
never@2895 | 197 | |
never@2895 | 198 | static void generate_ricochet_blob(MacroAssembler* _masm, |
never@2895 | 199 | // output params: |
never@2950 | 200 | int* bounce_offset, |
never@2950 | 201 | int* exception_offset, |
never@2950 | 202 | int* frame_size_in_words); |
never@2895 | 203 | |
never@2895 | 204 | static void enter_ricochet_frame(MacroAssembler* _masm, |
never@2895 | 205 | Register rcx_recv, |
never@2895 | 206 | Register rax_argv, |
never@2895 | 207 | address return_handler, |
never@2895 | 208 | Register rbx_temp); |
never@2895 | 209 | static void leave_ricochet_frame(MacroAssembler* _masm, |
never@2895 | 210 | Register rcx_recv, |
never@2895 | 211 | Register new_sp_reg, |
never@2895 | 212 | Register sender_pc_reg); |
never@2895 | 213 | |
never@2895 | 214 | static Address frame_address(int offset = 0) { |
never@2895 | 215 | // The RicochetFrame is found by subtracting a constant offset from rbp. |
never@2895 | 216 | return Address(rbp, - sender_link_offset_in_bytes() + offset); |
never@2895 | 217 | } |
never@2895 | 218 | |
never@2895 | 219 | static RicochetFrame* from_frame(const frame& fr) { |
never@2895 | 220 | address bp = (address) fr.fp(); |
never@2895 | 221 | RicochetFrame* rf = (RicochetFrame*)(bp - sender_link_offset_in_bytes()); |
never@2895 | 222 | rf->verify(); |
never@2895 | 223 | return rf; |
never@2895 | 224 | } |
never@2895 | 225 | |
never@2895 | 226 | static void verify_clean(MacroAssembler* _masm) NOT_DEBUG_RETURN; |
bdelsart@3445 | 227 | |
bdelsart@3451 | 228 | static void describe(const frame* fr, FrameValues& values, int frame_no) PRODUCT_RETURN; |
never@2895 | 229 | }; |
never@2895 | 230 | |
never@2895 | 231 | // Additional helper methods for MethodHandles code generation: |
never@2895 | 232 | public: |
never@2895 | 233 | static void load_klass_from_Class(MacroAssembler* _masm, Register klass_reg); |
never@2895 | 234 | static void load_conversion_vminfo(MacroAssembler* _masm, Register reg, Address conversion_field_addr); |
never@2895 | 235 | static void load_conversion_dest_type(MacroAssembler* _masm, Register reg, Address conversion_field_addr); |
never@2895 | 236 | |
never@2895 | 237 | static void load_stack_move(MacroAssembler* _masm, |
never@2895 | 238 | Register rdi_stack_move, |
never@2895 | 239 | Register rcx_amh, |
never@2895 | 240 | bool might_be_negative); |
never@2895 | 241 | |
never@2895 | 242 | static void insert_arg_slots(MacroAssembler* _masm, |
never@2895 | 243 | RegisterOrConstant arg_slots, |
never@2895 | 244 | Register rax_argslot, |
never@2895 | 245 | Register rbx_temp, Register rdx_temp); |
never@2895 | 246 | |
never@2895 | 247 | static void remove_arg_slots(MacroAssembler* _masm, |
never@2895 | 248 | RegisterOrConstant arg_slots, |
never@2895 | 249 | Register rax_argslot, |
never@2895 | 250 | Register rbx_temp, Register rdx_temp); |
never@2895 | 251 | |
never@2895 | 252 | static void push_arg_slots(MacroAssembler* _masm, |
never@2895 | 253 | Register rax_argslot, |
never@2895 | 254 | RegisterOrConstant slot_count, |
never@2895 | 255 | int skip_words_count, |
never@2895 | 256 | Register rbx_temp, Register rdx_temp); |
never@2895 | 257 | |
never@2895 | 258 | static void move_arg_slots_up(MacroAssembler* _masm, |
never@2895 | 259 | Register rbx_bottom, // invariant |
never@2895 | 260 | Address top_addr, // can use rax_temp |
never@2895 | 261 | RegisterOrConstant positive_distance_in_slots, |
never@2895 | 262 | Register rax_temp, Register rdx_temp); |
never@2895 | 263 | |
never@2895 | 264 | static void move_arg_slots_down(MacroAssembler* _masm, |
never@2895 | 265 | Address bottom_addr, // can use rax_temp |
never@2895 | 266 | Register rbx_top, // invariant |
never@2895 | 267 | RegisterOrConstant negative_distance_in_slots, |
never@2895 | 268 | Register rax_temp, Register rdx_temp); |
never@2895 | 269 | |
never@2895 | 270 | static void move_typed_arg(MacroAssembler* _masm, |
never@2895 | 271 | BasicType type, bool is_element, |
never@2895 | 272 | Address slot_dest, Address value_src, |
never@2895 | 273 | Register rbx_temp, Register rdx_temp); |
never@2895 | 274 | |
never@2895 | 275 | static void move_return_value(MacroAssembler* _masm, BasicType type, |
never@2895 | 276 | Address return_slot); |
never@2895 | 277 | |
never@2895 | 278 | static void verify_argslot(MacroAssembler* _masm, Register argslot_reg, |
never@2895 | 279 | const char* error_message) NOT_DEBUG_RETURN; |
never@2895 | 280 | |
never@2895 | 281 | static void verify_argslots(MacroAssembler* _masm, |
never@2895 | 282 | RegisterOrConstant argslot_count, |
never@2895 | 283 | Register argslot_reg, |
never@2895 | 284 | bool negate_argslot, |
never@2895 | 285 | const char* error_message) NOT_DEBUG_RETURN; |
never@2895 | 286 | |
never@2895 | 287 | static void verify_stack_move(MacroAssembler* _masm, |
never@2895 | 288 | RegisterOrConstant arg_slots, |
never@2895 | 289 | int direction) NOT_DEBUG_RETURN; |
never@2895 | 290 | |
never@2895 | 291 | static void verify_klass(MacroAssembler* _masm, |
never@2895 | 292 | Register obj, KlassHandle klass, |
never@2895 | 293 | const char* error_message = "wrong klass") NOT_DEBUG_RETURN; |
never@2895 | 294 | |
never@2895 | 295 | static void verify_method_handle(MacroAssembler* _masm, Register mh_reg) { |
never@2895 | 296 | verify_klass(_masm, mh_reg, SystemDictionaryHandles::MethodHandle_klass(), |
never@2895 | 297 | "reference is a MH"); |
never@2895 | 298 | } |
never@2895 | 299 | |
never@3005 | 300 | // Similar to InterpreterMacroAssembler::jump_from_interpreted. |
never@3005 | 301 | // Takes care of special dispatch from single stepping too. |
never@3005 | 302 | static void jump_from_method_handle(MacroAssembler* _masm, Register method, Register temp); |
never@3005 | 303 | |
never@2895 | 304 | static void trace_method_handle(MacroAssembler* _masm, const char* adaptername) PRODUCT_RETURN; |
never@2895 | 305 | |
never@2895 | 306 | static Register saved_last_sp_register() { |
never@2895 | 307 | // Should be in sharedRuntime, not here. |
never@2895 | 308 | return LP64_ONLY(r13) NOT_LP64(rsi); |
never@2895 | 309 | } |