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
field_offset(InstanceKlass * cls,const char * fieldname,Symbol * sigsym)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
find_InstanceKlass(const char * name,TRAPS)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
instance()50 const ForeignGlobals& ForeignGlobals::instance() {
51 static ForeignGlobals globals; // thread-safe lazy init-once (since C++11)
52 return globals;
53 }
54
parse_abi_descriptor(jobject jabi)55 const ABIDescriptor ForeignGlobals::parse_abi_descriptor(jobject jabi) {
56 return instance().parse_abi_descriptor_impl(jabi);
57 }
parse_buffer_layout(jobject jlayout)58 const BufferLayout ForeignGlobals::parse_buffer_layout(jobject jlayout) {
59 return instance().parse_buffer_layout_impl(jlayout);
60 }
61
parse_call_regs(jobject jconv)62 const CallRegs ForeignGlobals::parse_call_regs(jobject jconv) {
63 return instance().parse_call_regs_impl(jconv);
64 }
65
ForeignGlobals()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
calling_convention(BasicType * sig_bt,VMRegPair * parm_regs,uint argcnt) const102 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 }
131