1 /*
2 * Copyright (c) 2020, 2023, 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 "prims/vmstorage.hpp"
30 #include "runtime/sharedRuntime.hpp"
31 #include "utilities/growableArray.hpp"
32 #include "utilities/macros.hpp"
33
34 #include CPU_HEADER(foreignGlobals)
35
36 // Needs to match jdk.internal.foreign.abi.StubLocations in Java code.
37 // Placeholder locations to be filled in by the code gen code.
38 class StubLocations {
39 public:
40 enum Location : uint32_t {
41 TARGET_ADDRESS,
42 RETURN_BUFFER,
43 CAPTURED_STATE_BUFFER,
44 LOCATION_LIMIT
45 };
46 private:
47 VMStorage _locs[LOCATION_LIMIT];
48 public:
49 StubLocations();
50
51 void set(uint32_t loc, VMStorage storage);
52 void set_frame_data(uint32_t loc, int offset);
53 VMStorage get(uint32_t loc) const;
54 VMStorage get(VMStorage placeholder) const;
55 int data_offset(uint32_t loc) const;
56 };
57
58 // C++ 'mirror' of jdk.internal.foreign.abi.UpcallLinker.CallRegs
59 struct CallRegs {
60 GrowableArray<VMStorage> _arg_regs;
61 GrowableArray<VMStorage> _ret_regs;
62
63 CallRegs(int num_args, int num_rets)
64 : _arg_regs(num_args), _ret_regs(num_rets) {}
65 };
66
67
68 class ForeignGlobals {
69 private:
70 template<typename T>
71 static void parse_register_array(objArrayOop jarray, StorageType type_index, GrowableArray<T>& array, T (*converter)(int));
72
73 public:
74 static bool is_foreign_linker_supported();
75
76 // Helpers for translating from the Java to C++ representation
77 static const ABIDescriptor parse_abi_descriptor(jobject jabi);
78 static const CallRegs parse_call_regs(jobject jconv);
79 static VMStorage parse_vmstorage(oop storage);
80
81 // Adapter from SharedRuntime::java_calling_convention to a 'single VMStorage per value' form.
82 // Doesn't assign (invalid) storage for T_VOID entries in the signature, which are instead ignored.
83 static int java_calling_convention(const BasicType* signature, int num_args, GrowableArray<VMStorage>& out_regs);
84
85 // Computes the space (in bytes) that is taken up by stack arguments
86 static int compute_out_arg_bytes(const GrowableArray<VMStorage>& out_regs);
87
88 // Replace placeholders (see class StubLocations above) with actual locations in a stub frame
89 static GrowableArray<VMStorage> replace_place_holders(const GrowableArray<VMStorage>& regs, const StubLocations& locs);
90
91 // The receiver method handle for upcalls is injected manually into the argument list by the upcall stub. We need a
92 // filtered list to generate an argument shuffle for the rest of the arguments.
93 static GrowableArray<VMStorage> upcall_filter_receiver_reg(const GrowableArray<VMStorage>& unfiltered_regs);
94
95 // Oop offsets are not passed on to native code.
96 // Filter out the registers of oop offsets to create a list that we can pass to ArgumentShuffle.
97 static GrowableArray<VMStorage> downcall_filter_offset_regs(const GrowableArray<VMStorage>& regs, BasicType* signature,
98 int num_args, bool& has_objects);
99 };
100
101 // Helper class useful for generating spills and fills of a set of registers.
102 class RegSpiller {
103 GrowableArray<VMStorage> _regs;
104 int _spill_size_bytes;
105 public:
106 RegSpiller(const GrowableArray<VMStorage>& regs) : _regs(regs), _spill_size_bytes(compute_spill_area(regs)) {
107 }
108
109 int spill_size_bytes() const { return _spill_size_bytes; }
110 void generate_spill(MacroAssembler* masm, int rsp_offset) const { return generate(masm, rsp_offset, true); }
111 void generate_fill(MacroAssembler* masm, int rsp_offset) const { return generate(masm, rsp_offset, false); }
112
113 private:
114 static int compute_spill_area(const GrowableArray<VMStorage>& regs);
115 void generate(MacroAssembler* masm, int rsp_offset, bool is_spill) const;
116
117 static int pd_reg_size(VMStorage reg);
118 static void pd_store_reg(MacroAssembler* masm, int offset, VMStorage reg);
119 static void pd_load_reg(MacroAssembler* masm, int offset, VMStorage reg);
120 };
121
122 // Class used to compute and generate a shuffle between 2 lists of VMStorages.
123 // The lists must have the same size.
124 // Each VMStorage in the source list (in_regs) is shuffled into the
125 // the VMStorage at the same index in the destination list (out_regs).
126 // This class helps to automatically compute an order of moves that makes
127 // sure not to destroy values accidentally by interfering moves, in case the
128 // source and destination registers overlap.
129 class ArgumentShuffle {
130 private:
131 class ComputeMoveOrder;
132 struct Move {
133 VMStorage from;
134 VMStorage to;
135 };
136
137 GrowableArray<Move> _moves;
138 public:
139 ArgumentShuffle(
140 const GrowableArray<VMStorage>& in_regs,
141 const GrowableArray<VMStorage>& out_regs,
142 VMStorage shuffle_temp);
143
144 void generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias) const {
145 pd_generate(masm, tmp, in_stk_bias, out_stk_bias);
146 }
147
148 void print_on(outputStream* os) const;
149 private:
150 void pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias) const;
151 };
152
153 #endif // SHARE_PRIMS_FOREIGN_GLOBALS