1 /* 2 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 #ifndef SHARE_PRIMS_FOREIGN_GLOBALS 25 #define SHARE_PRIMS_FOREIGN_GLOBALS 26 27 #include "code/vmreg.hpp" 28 #include "oops/oopsHierarchy.hpp" 29 #include "runtime/sharedRuntime.hpp" 30 #include "utilities/growableArray.hpp" 31 #include "utilities/macros.hpp" 32 33 #include CPU_HEADER(foreign_globals) 34 35 class CallConvClosure { 36 public: 37 virtual int calling_convention(BasicType* sig_bt, VMRegPair* regs, int num_args) const = 0; 38 }; 39 40 struct CallRegs { 41 VMReg* _arg_regs; 42 int _args_length; 43 44 VMReg* _ret_regs; 45 int _rets_length; 46 }; 47 48 class ForeignGlobals { 49 private: 50 struct { 51 int inputStorage_offset; 52 int outputStorage_offset; 53 int volatileStorage_offset; 54 int stackAlignment_offset; 55 int shadowSpace_offset; 56 int targetAddrStorage_offset; 57 int retBufAddrStorage_offset; 58 } ABI; 59 60 struct { 61 int index_offset; 62 int type_offset; 63 } VMS; 64 65 struct { 66 int arg_regs_offset; 67 int ret_regs_offset; 68 } CallConvOffsets; 69 70 ForeignGlobals(); 71 72 static const ForeignGlobals& instance(); 73 74 template<typename T, typename Func> 75 void loadArray(objArrayOop jarray, int type_index, GrowableArray<T>& array, Func converter) const; 76 77 const ABIDescriptor parse_abi_descriptor_impl(jobject jabi) const; 78 const CallRegs parse_call_regs_impl(jobject jconv) const; 79 80 VMReg parse_vmstorage(oop storage) const; 81 public: 82 static const ABIDescriptor parse_abi_descriptor(jobject jabi); 83 static const CallRegs parse_call_regs(jobject jconv); 84 85 static VMReg vmstorage_to_vmreg(int type, int index); 86 }; 87 88 89 90 class JavaCallConv : public CallConvClosure { 91 public: 92 int calling_convention(BasicType* sig_bt, VMRegPair* regs, int num_args) const override { 93 return SharedRuntime::java_calling_convention(sig_bt, regs, num_args); 94 } 95 }; 96 97 class NativeCallConv : public CallConvClosure { 98 const VMReg* _input_regs; 99 int _input_regs_length; 100 public: 101 NativeCallConv(const VMReg* input_regs, int input_regs_length) : 102 _input_regs(input_regs), 103 _input_regs_length(input_regs_length) { 104 } 105 NativeCallConv(const GrowableArray<VMReg>& input_regs) 106 : NativeCallConv(input_regs.data(), input_regs.length()) {} 107 108 int calling_convention(BasicType* sig_bt, VMRegPair* out_regs, int num_args) const override; 109 }; 110 111 class RegSpiller { 112 const VMReg* _regs; 113 int _num_regs; 114 int _spill_size_bytes; 115 public: 116 RegSpiller(const VMReg* regs, int num_regs) : 117 _regs(regs), _num_regs(num_regs), 118 _spill_size_bytes(compute_spill_area(regs, num_regs)) { 119 } 120 RegSpiller(const GrowableArray<VMReg>& regs) : RegSpiller(regs.data(), regs.length()) { 121 } 122 123 int spill_size_bytes() const { return _spill_size_bytes; } 124 void generate_spill(MacroAssembler* masm, int rsp_offset) const { return generate(masm, rsp_offset, true); } 125 void generate_fill(MacroAssembler* masm, int rsp_offset) const { return generate(masm, rsp_offset, false); } 126 127 private: 128 static int compute_spill_area(const VMReg* regs, int num_regs); 129 void generate(MacroAssembler* masm, int rsp_offset, bool is_spill) const; 130 131 static int pd_reg_size(VMReg reg); 132 static void pd_store_reg(MacroAssembler* masm, int offset, VMReg reg); 133 static void pd_load_reg(MacroAssembler* masm, int offset, VMReg reg); 134 }; 135 136 struct Move { 137 BasicType bt; 138 VMRegPair from; 139 VMRegPair to; 140 }; 141 142 class ArgumentShuffle { 143 private: 144 GrowableArray<Move> _moves; 145 int _out_arg_stack_slots; 146 public: 147 ArgumentShuffle( 148 BasicType* in_sig_bt, int num_in_args, 149 BasicType* out_sig_bt, int num_out_args, 150 const CallConvClosure* input_conv, const CallConvClosure* output_conv, 151 VMReg shuffle_temp); 152 153 int out_arg_stack_slots() const { return _out_arg_stack_slots; } 154 void generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const { 155 pd_generate(masm, tmp, in_stk_bias, out_stk_bias); 156 } 157 158 void print_on(outputStream* os) const; 159 private: 160 void pd_generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const; 161 }; 162 163 #endif // SHARE_PRIMS_FOREIGN_GLOBALS