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 #include "precompiled.hpp"
 25 #include "runtime/jniHandles.hpp"
 26 #include "runtime/jniHandles.inline.hpp"
 27 #include "oops/typeArrayOop.inline.hpp"
 28 #include "prims/foreign_globals.hpp"
 29 #include "prims/foreign_globals.inline.hpp"
 30 
 31 bool ABIDescriptor::is_volatile_reg(Register reg) const {
 32     return _integer_argument_registers.contains(reg)
 33         || _integer_additional_volatile_registers.contains(reg);
 34 }
 35 
 36 bool ABIDescriptor::is_volatile_reg(XMMRegister reg) const {
 37     return _vector_argument_registers.contains(reg)
 38         || _vector_additional_volatile_registers.contains(reg);
 39 }
 40 
 41 #define INTEGER_TYPE 0
 42 #define VECTOR_TYPE 1
 43 #define X87_TYPE 2
 44 
 45 const ABIDescriptor ForeignGlobals::parse_abi_descriptor_impl(jobject jabi) const {
 46   oop abi_oop = JNIHandles::resolve_non_null(jabi);
 47   ABIDescriptor abi;
 48 
 49   objArrayOop inputStorage = cast<objArrayOop>(abi_oop->obj_field(ABI.inputStorage_offset));
 50   loadArray(inputStorage, INTEGER_TYPE, abi._integer_argument_registers, as_Register);
 51   loadArray(inputStorage, VECTOR_TYPE, abi._vector_argument_registers, as_XMMRegister);
 52 
 53   objArrayOop outputStorage = cast<objArrayOop>(abi_oop->obj_field(ABI.outputStorage_offset));
 54   loadArray(outputStorage, INTEGER_TYPE, abi._integer_return_registers, as_Register);
 55   loadArray(outputStorage, VECTOR_TYPE, abi._vector_return_registers, as_XMMRegister);
 56   objArrayOop subarray = cast<objArrayOop>(outputStorage->obj_at(X87_TYPE));
 57   abi._X87_return_registers_noof = subarray->length();
 58 
 59   objArrayOop volatileStorage = cast<objArrayOop>(abi_oop->obj_field(ABI.volatileStorage_offset));
 60   loadArray(volatileStorage, INTEGER_TYPE, abi._integer_additional_volatile_registers, as_Register);
 61   loadArray(volatileStorage, VECTOR_TYPE, abi._vector_additional_volatile_registers, as_XMMRegister);
 62 
 63   abi._stack_alignment_bytes = abi_oop->int_field(ABI.stackAlignment_offset);
 64   abi._shadow_space_bytes = abi_oop->int_field(ABI.shadowSpace_offset);
 65 
 66   return abi;
 67 }
 68 
 69 const BufferLayout ForeignGlobals::parse_buffer_layout_impl(jobject jlayout) const {
 70   oop layout_oop = JNIHandles::resolve_non_null(jlayout);
 71   BufferLayout layout;
 72 
 73   layout.stack_args_bytes = layout_oop->long_field(BL.stack_args_bytes_offset);
 74   layout.stack_args = layout_oop->long_field(BL.stack_args_offset);
 75   layout.arguments_next_pc = layout_oop->long_field(BL.arguments_next_pc_offset);
 76 
 77   typeArrayOop input_offsets = cast<typeArrayOop>(layout_oop->obj_field(BL.input_type_offsets_offset));
 78   layout.arguments_integer = (size_t) input_offsets->long_at(INTEGER_TYPE);
 79   layout.arguments_vector = (size_t) input_offsets->long_at(VECTOR_TYPE);
 80 
 81   typeArrayOop output_offsets = cast<typeArrayOop>(layout_oop->obj_field(BL.output_type_offsets_offset));
 82   layout.returns_integer = (size_t) output_offsets->long_at(INTEGER_TYPE);
 83   layout.returns_vector = (size_t) output_offsets->long_at(VECTOR_TYPE);
 84   layout.returns_x87 = (size_t) output_offsets->long_at(X87_TYPE);
 85 
 86   layout.buffer_size = layout_oop->long_field(BL.size_offset);
 87 
 88   return layout;
 89 }
 90 
 91 const CallRegs ForeignGlobals::parse_call_regs_impl(jobject jconv) const {
 92   oop conv_oop = JNIHandles::resolve_non_null(jconv);
 93   objArrayOop arg_regs_oop = cast<objArrayOop>(conv_oop->obj_field(CallConvOffsets.arg_regs_offset));
 94   objArrayOop ret_regs_oop = cast<objArrayOop>(conv_oop->obj_field(CallConvOffsets.ret_regs_offset));
 95 
 96   CallRegs result;
 97   result._args_length = arg_regs_oop->length();
 98   result._arg_regs = NEW_RESOURCE_ARRAY(VMReg, result._args_length);
 99 
100   result._rets_length = ret_regs_oop->length();
101   result._ret_regs = NEW_RESOURCE_ARRAY(VMReg, result._rets_length);
102 
103   for (int i = 0; i < result._args_length; i++) {
104     oop storage = arg_regs_oop->obj_at(i);
105     jint index = storage->int_field(VMS.index_offset);
106     jint type = storage->int_field(VMS.type_offset);
107     result._arg_regs[i] = VMRegImpl::vmStorageToVMReg(type, index);
108   }
109 
110   for (int i = 0; i < result._rets_length; i++) {
111     oop storage = ret_regs_oop->obj_at(i);
112     jint index = storage->int_field(VMS.index_offset);
113     jint type = storage->int_field(VMS.type_offset);
114     result._ret_regs[i] = VMRegImpl::vmStorageToVMReg(type, index);
115   }
116 
117   return result;
118 }