1 /* 2 * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2019, 2021, Arm Limited. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 #include "precompiled.hpp" 26 #include "code/vmreg.inline.hpp" 27 #include "runtime/jniHandles.hpp" 28 #include "runtime/jniHandles.inline.hpp" 29 #include "oops/typeArrayOop.inline.hpp" 30 #include "oops/oopCast.inline.hpp" 31 #include "opto/matcher.hpp" 32 #include "prims/foreign_globals.hpp" 33 #include "prims/foreign_globals.inline.hpp" 34 #include "utilities/formatBuffer.hpp" 35 36 bool ABIDescriptor::is_volatile_reg(Register reg) const { 37 return _integer_argument_registers.contains(reg) 38 || _integer_additional_volatile_registers.contains(reg); 39 } 40 41 bool ABIDescriptor::is_volatile_reg(FloatRegister reg) const { 42 return _vector_argument_registers.contains(reg) 43 || _vector_additional_volatile_registers.contains(reg); 44 } 45 46 #define INTEGER_TYPE 0 47 #define VECTOR_TYPE 1 48 49 const ABIDescriptor ForeignGlobals::parse_abi_descriptor_impl(jobject jabi) const { 50 oop abi_oop = JNIHandles::resolve_non_null(jabi); 51 ABIDescriptor abi; 52 constexpr Register (*to_Register)(int) = as_Register; 53 54 objArrayOop inputStorage = oop_cast<objArrayOop>(abi_oop->obj_field(ABI.inputStorage_offset)); 55 loadArray(inputStorage, INTEGER_TYPE, abi._integer_argument_registers, to_Register); 56 loadArray(inputStorage, VECTOR_TYPE, abi._vector_argument_registers, as_FloatRegister); 57 58 objArrayOop outputStorage = oop_cast<objArrayOop>(abi_oop->obj_field(ABI.outputStorage_offset)); 59 loadArray(outputStorage, INTEGER_TYPE, abi._integer_return_registers, to_Register); 60 loadArray(outputStorage, VECTOR_TYPE, abi._vector_return_registers, as_FloatRegister); 61 62 objArrayOop volatileStorage = oop_cast<objArrayOop>(abi_oop->obj_field(ABI.volatileStorage_offset)); 63 loadArray(volatileStorage, INTEGER_TYPE, abi._integer_additional_volatile_registers, to_Register); 64 loadArray(volatileStorage, VECTOR_TYPE, abi._vector_additional_volatile_registers, as_FloatRegister); 65 66 abi._stack_alignment_bytes = abi_oop->int_field(ABI.stackAlignment_offset); 67 abi._shadow_space_bytes = abi_oop->int_field(ABI.shadowSpace_offset); 68 69 abi._target_addr_reg = parse_vmstorage(abi_oop->obj_field(ABI.targetAddrStorage_offset))->as_Register(); 70 abi._ret_buf_addr_reg = parse_vmstorage(abi_oop->obj_field(ABI.retBufAddrStorage_offset))->as_Register(); 71 72 return abi; 73 } 74 75 enum class RegType { 76 INTEGER = 0, 77 VECTOR = 1, 78 STACK = 3 79 }; 80 81 VMReg ForeignGlobals::vmstorage_to_vmreg(int type, int index) { 82 switch(static_cast<RegType>(type)) { 83 case RegType::INTEGER: return ::as_Register(index)->as_VMReg(); 84 case RegType::VECTOR: return ::as_FloatRegister(index)->as_VMReg(); 85 case RegType::STACK: return VMRegImpl::stack2reg(index LP64_ONLY(* 2)); 86 } 87 return VMRegImpl::Bad(); 88 } 89 90 int RegSpiller::pd_reg_size(VMReg reg) { 91 if (reg->is_Register()) { 92 return 8; 93 } else if (reg->is_FloatRegister()) { 94 bool use_sve = Matcher::supports_scalable_vector(); 95 if (use_sve) { 96 return Matcher::scalable_vector_reg_size(T_BYTE); 97 } 98 return 16; 99 } 100 return 0; // stack and BAD 101 } 102 103 void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMReg reg) { 104 if (reg->is_Register()) { 105 masm->spill(reg->as_Register(), true, offset); 106 } else if (reg->is_FloatRegister()) { 107 bool use_sve = Matcher::supports_scalable_vector(); 108 if (use_sve) { 109 masm->spill_sve_vector(reg->as_FloatRegister(), offset, Matcher::scalable_vector_reg_size(T_BYTE)); 110 } else { 111 masm->spill(reg->as_FloatRegister(), masm->Q, offset); 112 } 113 } else { 114 // stack and BAD 115 } 116 } 117 118 void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMReg reg) { 119 if (reg->is_Register()) { 120 masm->unspill(reg->as_Register(), true, offset); 121 } else if (reg->is_FloatRegister()) { 122 bool use_sve = Matcher::supports_scalable_vector(); 123 if (use_sve) { 124 masm->unspill_sve_vector(reg->as_FloatRegister(), offset, Matcher::scalable_vector_reg_size(T_BYTE)); 125 } else { 126 masm->unspill(reg->as_FloatRegister(), masm->Q, offset); 127 } 128 } else { 129 // stack and BAD 130 } 131 } 132 133 void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const { 134 assert(in_stk_bias == 0 && out_stk_bias == 0, "bias not implemented"); 135 Register tmp_reg = tmp->as_Register(); 136 for (int i = 0; i < _moves.length(); i++) { 137 Move move = _moves.at(i); 138 BasicType arg_bt = move.bt; 139 VMRegPair from_vmreg = move.from; 140 VMRegPair to_vmreg = move.to; 141 142 masm->block_comment(err_msg("bt=%s", null_safe_string(type2name(arg_bt)))); 143 switch (arg_bt) { 144 case T_BOOLEAN: 145 case T_BYTE: 146 case T_SHORT: 147 case T_CHAR: 148 case T_INT: 149 masm->move32_64(from_vmreg, to_vmreg, tmp_reg); 150 break; 151 152 case T_FLOAT: 153 masm->float_move(from_vmreg, to_vmreg, tmp_reg); 154 break; 155 156 case T_DOUBLE: 157 masm->double_move(from_vmreg, to_vmreg, tmp_reg); 158 break; 159 160 case T_LONG : 161 masm->long_move(from_vmreg, to_vmreg, tmp_reg); 162 break; 163 164 default: 165 fatal("found in upcall args: %s", type2name(arg_bt)); 166 } 167 } 168 }