view src/cpu/sparc/vm/methodHandles_sparc.hpp @ 5762:b30cced39597

generalized functionality for finding classes based on searching for patterns in source code and moved it from commands.py to mx.py used above functionality to find classes manually excluded from JaCoCo processing
author Doug Simon <doug.simon@oracle.com>
date Wed, 04 Jul 2012 21:56:48 +0200
parents 5dbed2f542ff
children 1d7922586cf6
line wrap: on
line source

/*
 * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 * 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 */ {
  adapter_code_size = NOT_LP64(23000 DEBUG_ONLY(+ 40000)) LP64_ONLY(35000 DEBUG_ONLY(+ 50000))
};

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;

  static void describe(const frame* fr, FrameValues& values, int frame_no) PRODUCT_RETURN;
};

// 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");
  }

  // 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);

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