methodHandles_sparc.hpp 10.5 KB
Newer Older
1
/*
2
 * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

// Platform-specific definitions for method handles.
// These definitions are inlined into class MethodHandles.

// Adapters
enum /* platform_dependent_constants */ {
30
  adapter_code_size = NOT_LP64(23000 DEBUG_ONLY(+ 40000)) LP64_ONLY(35000 DEBUG_ONLY(+ 50000))
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
};

public:

class RicochetFrame : public ResourceObj {
  friend class MethodHandles;

 private:
  /*
    RF field            x86                 SPARC
    sender_pc           *(rsp+0)            I7-0x8
    sender_link         rbp                 I6+BIAS
    exact_sender_sp     rsi/r13             I5_savedSP
    conversion          *(rcx+&amh_conv)    L5_conv
    saved_args_base     rax                 L4_sab (cf. Gargs = G4)
    saved_args_layout   #NULL               L3_sal
    saved_target        *(rcx+&mh_vmtgt)    L2_stgt
    continuation        #STUB_CON           L1_cont
   */
  static const Register L1_continuation     ;  // what to do when control gets back here
  static const Register L2_saved_target     ;  // target method handle to invoke on saved_args
  static const Register L3_saved_args_layout;  // caching point for MethodTypeForm.vmlayout cookie
  static const Register L4_saved_args_base  ;  // base of pushed arguments (slot 0, arg N) (-3)
  static const Register L5_conversion       ;  // misc. information from original AdapterMethodHandle (-2)

  frame _fr;

  RicochetFrame(const frame& fr) : _fr(fr) { }

  intptr_t* register_addr(Register reg) const  {
    assert((_fr.sp() + reg->sp_offset_in_saved_window()) == _fr.register_addr(reg), "must agree");
    return _fr.register_addr(reg);
  }
  intptr_t  register_value(Register reg) const { return *register_addr(reg); }

 public:
  intptr_t* continuation() const        { return (intptr_t*) register_value(L1_continuation); }
  oop       saved_target() const        { return (oop)       register_value(L2_saved_target); }
  oop       saved_args_layout() const   { return (oop)       register_value(L3_saved_args_layout); }
  intptr_t* saved_args_base() const     { return (intptr_t*) register_value(L4_saved_args_base); }
  intptr_t  conversion() const          { return             register_value(L5_conversion); }
  intptr_t* exact_sender_sp() const     { return (intptr_t*) register_value(I5_savedSP); }
  intptr_t* sender_link() const         { return _fr.sender_sp(); }  // XXX
  address   sender_pc() const           { return _fr.sender_pc(); }

  // This value is not used for much, but it apparently must be nonzero.
  static int frame_size_in_bytes()              { return wordSize * 4; }

  intptr_t* extended_sender_sp() const  { return saved_args_base(); }

  intptr_t  return_value_slot_number() const {
    return adapter_conversion_vminfo(conversion());
  }
  BasicType return_value_type() const {
    return adapter_conversion_dest_type(conversion());
  }
  bool has_return_value_slot() const {
    return return_value_type() != T_VOID;
  }
  intptr_t* return_value_slot_addr() const {
    assert(has_return_value_slot(), "");
    return saved_arg_slot_addr(return_value_slot_number());
  }
  intptr_t* saved_target_slot_addr() const {
    return saved_arg_slot_addr(saved_args_length());
  }
  intptr_t* saved_arg_slot_addr(int slot) const {
    assert(slot >= 0, "");
    return (intptr_t*)( (address)saved_args_base() + (slot * Interpreter::stackElementSize) );
  }

  jint      saved_args_length() const;
  jint      saved_arg_offset(int arg) const;

  // GC interface
  oop*  saved_target_addr()                     { return (oop*)register_addr(L2_saved_target); }
  oop*  saved_args_layout_addr()                { return (oop*)register_addr(L3_saved_args_layout); }

  oop  compute_saved_args_layout(bool read_cache, bool write_cache);

#ifdef ASSERT
  // The magic number is supposed to help find ricochet frames within the bytes of stack dumps.
  enum { MAGIC_NUMBER_1 = 0xFEED03E, MAGIC_NUMBER_2 = 0xBEEF03E };
  static const Register L0_magic_number_1   ;  // cookie for debugging, at start of RSA
  static Address magic_number_2_addr()  { return Address(L4_saved_args_base, -wordSize); }
  intptr_t magic_number_1() const       { return register_value(L0_magic_number_1); }
  intptr_t magic_number_2() const       { return saved_args_base()[-1]; }
#endif //ASSERT

 public:
  enum { RETURN_VALUE_PLACEHOLDER = (NOT_DEBUG(0) DEBUG_ONLY(42)) };

  void verify() const NOT_DEBUG_RETURN; // check for MAGIC_NUMBER, etc.

  static void generate_ricochet_blob(MacroAssembler* _masm,
                                     // output params:
                                     int* bounce_offset,
                                     int* exception_offset,
                                     int* frame_size_in_words);

  static void enter_ricochet_frame(MacroAssembler* _masm,
                                   Register recv_reg,
                                   Register argv_reg,
                                   address return_handler);

  static void leave_ricochet_frame(MacroAssembler* _masm,
                                   Register recv_reg,
                                   Register new_sp_reg,
                                   Register sender_pc_reg);

  static RicochetFrame* from_frame(const frame& fr) {
    RicochetFrame* rf = new RicochetFrame(fr);
    rf->verify();
    return rf;
  }

  static void verify_clean(MacroAssembler* _masm) NOT_DEBUG_RETURN;
148

149
  static void describe(const frame* fr, FrameValues& values, int frame_no) PRODUCT_RETURN;
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
};

// Additional helper methods for MethodHandles code generation:
public:
  static void load_klass_from_Class(MacroAssembler* _masm, Register klass_reg, Register temp_reg, Register temp2_reg);
  static void load_conversion_vminfo(MacroAssembler* _masm, Address conversion_field_addr, Register reg);
  static void extract_conversion_vminfo(MacroAssembler* _masm, Register conversion_field_reg, Register reg);
  static void extract_conversion_dest_type(MacroAssembler* _masm, Register conversion_field_reg, Register reg);

  static void load_stack_move(MacroAssembler* _masm,
                              Address G3_amh_conversion,
                              Register G5_stack_move);

  static void insert_arg_slots(MacroAssembler* _masm,
                               RegisterOrConstant arg_slots,
                               Register argslot_reg,
                               Register temp_reg, Register temp2_reg, Register temp3_reg);

  static void remove_arg_slots(MacroAssembler* _masm,
                               RegisterOrConstant arg_slots,
                               Register argslot_reg,
                               Register temp_reg, Register temp2_reg, Register temp3_reg);

  static void push_arg_slots(MacroAssembler* _masm,
                             Register argslot_reg,
                             RegisterOrConstant slot_count,
                             Register temp_reg, Register temp2_reg);

  static void move_arg_slots_up(MacroAssembler* _masm,
                                Register bottom_reg,  // invariant
                                Address  top_addr,    // can use temp_reg
                                RegisterOrConstant positive_distance_in_slots,
                                Register temp_reg, Register temp2_reg);

  static void move_arg_slots_down(MacroAssembler* _masm,
                                  Address  bottom_addr,  // can use temp_reg
                                  Register top_reg,      // invariant
                                  RegisterOrConstant negative_distance_in_slots,
                                  Register temp_reg, Register temp2_reg);

  static void move_typed_arg(MacroAssembler* _masm,
                             BasicType type, bool is_element,
                             Address value_src, Address slot_dest,
                             Register temp_reg);

  static void move_return_value(MacroAssembler* _masm, BasicType type,
                                Address return_slot);

  static void verify_argslot(MacroAssembler* _masm, Register argslot_reg,
                             Register temp_reg,
                             const char* error_message) NOT_DEBUG_RETURN;

  static void verify_argslots(MacroAssembler* _masm,
                              RegisterOrConstant argslot_count,
                              Register argslot_reg,
                              Register temp_reg,
                              Register temp2_reg,
                              bool negate_argslot,
                              const char* error_message) NOT_DEBUG_RETURN;

  static void verify_stack_move(MacroAssembler* _masm,
                                RegisterOrConstant arg_slots,
                                int direction) NOT_DEBUG_RETURN;

  static void verify_klass(MacroAssembler* _masm,
                           Register obj_reg, KlassHandle klass,
                           Register temp_reg, Register temp2_reg,
                           const char* error_message = "wrong klass") NOT_DEBUG_RETURN;

  static void verify_method_handle(MacroAssembler* _masm, Register mh_reg,
                                   Register temp_reg, Register temp2_reg) {
    verify_klass(_masm, mh_reg, SystemDictionaryHandles::MethodHandle_klass(),
                 temp_reg, temp2_reg,
                 "reference is a MH");
  }

226 227 228 229
  // Similar to InterpreterMacroAssembler::jump_from_interpreted.
  // Takes care of special dispatch from single stepping too.
  static void jump_from_method_handle(MacroAssembler* _masm, Register method, Register temp, Register temp2);

230
  static void trace_method_handle(MacroAssembler* _masm, const char* adaptername) PRODUCT_RETURN;