src/cpu/x86/vm/methodHandles_x86.hpp

changeset 2895
167b70ff3abc
child 2950
cba7b5c2d53f
     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 +  }

mercurial