1 /* 2 * Copyright (c) 2020, 2021, 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 "foreign_globals.hpp" 26 #include "classfile/symbolTable.hpp" 27 #include "classfile/systemDictionary.hpp" 28 #include "classfile/vmSymbols.hpp" 29 #include "memory/resourceArea.hpp" 30 #include "runtime/fieldDescriptor.hpp" 31 #include "runtime/fieldDescriptor.inline.hpp" 32 33 #define FOREIGN_ABI "jdk/internal/foreign/abi/" 34 35 static int field_offset(InstanceKlass* cls, const char* fieldname, Symbol* sigsym) { 36 TempNewSymbol fieldnamesym = SymbolTable::new_symbol(fieldname, (int)strlen(fieldname)); 37 fieldDescriptor fd; 38 bool success = cls->find_field(fieldnamesym, sigsym, false, &fd); 39 assert(success, "Field not found"); 40 return fd.offset(); 41 } 42 43 static InstanceKlass* find_InstanceKlass(const char* name, TRAPS) { 44 TempNewSymbol sym = SymbolTable::new_symbol(name, (int)strlen(name)); 45 Klass* k = SystemDictionary::resolve_or_null(sym, Handle(), Handle(), THREAD); 46 assert(k != nullptr, "Can not find class: %s", name); 47 return InstanceKlass::cast(k); 48 } 49 50 const ForeignGlobals& ForeignGlobals::instance() { 51 static ForeignGlobals globals; // thread-safe lazy init-once (since C++11) 52 return globals; 53 } 54 55 const ABIDescriptor ForeignGlobals::parse_abi_descriptor(jobject jabi) { 56 return instance().parse_abi_descriptor_impl(jabi); 57 } 58 const BufferLayout ForeignGlobals::parse_buffer_layout(jobject jlayout) { 59 return instance().parse_buffer_layout_impl(jlayout); 60 } 61 62 const CallRegs ForeignGlobals::parse_call_regs(jobject jconv) { 63 return instance().parse_call_regs_impl(jconv); 64 } 65 66 ForeignGlobals::ForeignGlobals() { 67 JavaThread* current_thread = JavaThread::current(); 68 ResourceMark rm(current_thread); 69 70 // ABIDescriptor 71 InstanceKlass* k_ABI = find_InstanceKlass(FOREIGN_ABI "ABIDescriptor", current_thread); 72 const char* strVMSArrayArray = "[[L" FOREIGN_ABI "VMStorage;"; 73 Symbol* symVMSArrayArray = SymbolTable::new_symbol(strVMSArrayArray); 74 ABI.inputStorage_offset = field_offset(k_ABI, "inputStorage", symVMSArrayArray); 75 ABI.outputStorage_offset = field_offset(k_ABI, "outputStorage", symVMSArrayArray); 76 ABI.volatileStorage_offset = field_offset(k_ABI, "volatileStorage", symVMSArrayArray); 77 ABI.stackAlignment_offset = field_offset(k_ABI, "stackAlignment", vmSymbols::int_signature()); 78 ABI.shadowSpace_offset = field_offset(k_ABI, "shadowSpace", vmSymbols::int_signature()); 79 80 // VMStorage 81 InstanceKlass* k_VMS = find_InstanceKlass(FOREIGN_ABI "VMStorage", current_thread); 82 VMS.index_offset = field_offset(k_VMS, "index", vmSymbols::int_signature()); 83 VMS.type_offset = field_offset(k_VMS, "type", vmSymbols::int_signature()); 84 85 // BufferLayout 86 InstanceKlass* k_BL = find_InstanceKlass(FOREIGN_ABI "BufferLayout", current_thread); 87 BL.size_offset = field_offset(k_BL, "size", vmSymbols::long_signature()); 88 BL.arguments_next_pc_offset = field_offset(k_BL, "arguments_next_pc", vmSymbols::long_signature()); 89 BL.stack_args_bytes_offset = field_offset(k_BL, "stack_args_bytes", vmSymbols::long_signature()); 90 BL.stack_args_offset = field_offset(k_BL, "stack_args", vmSymbols::long_signature()); 91 BL.input_type_offsets_offset = field_offset(k_BL, "input_type_offsets", vmSymbols::long_array_signature()); 92 BL.output_type_offsets_offset = field_offset(k_BL, "output_type_offsets", vmSymbols::long_array_signature()); 93 94 // CallRegs 95 const char* strVMSArray = "[L" FOREIGN_ABI "VMStorage;"; 96 Symbol* symVMSArray = SymbolTable::new_symbol(strVMSArray); 97 InstanceKlass* k_CC = find_InstanceKlass(FOREIGN_ABI "ProgrammableUpcallHandler$CallRegs", current_thread); 98 CallConvOffsets.arg_regs_offset = field_offset(k_CC, "argRegs", symVMSArray); 99 CallConvOffsets.ret_regs_offset = field_offset(k_CC, "retRegs", symVMSArray); 100 } 101 102 void CallRegs::calling_convention(BasicType* sig_bt, VMRegPair *parm_regs, uint argcnt) const { 103 int src_pos = 0; 104 for (uint i = 0; i < argcnt; i++) { 105 switch (sig_bt[i]) { 106 case T_BOOLEAN: 107 case T_CHAR: 108 case T_BYTE: 109 case T_SHORT: 110 case T_INT: 111 case T_FLOAT: 112 assert(src_pos < _args_length, "oob"); 113 parm_regs[i].set1(_arg_regs[src_pos++]); 114 break; 115 case T_LONG: 116 case T_DOUBLE: 117 assert((i + 1) < argcnt && sig_bt[i + 1] == T_VOID, "expecting half"); 118 assert(src_pos < _args_length, "oob"); 119 parm_regs[i].set2(_arg_regs[src_pos++]); 120 break; 121 case T_VOID: // Halves of longs and doubles 122 assert(i != 0 && (sig_bt[i - 1] == T_LONG || sig_bt[i - 1] == T_DOUBLE), "expecting half"); 123 parm_regs[i].set_bad(); 124 break; 125 default: 126 ShouldNotReachHere(); 127 break; 128 } 129 } 130 }