Line data Source code
1 : /**
2 : Copyright (c) 2024 Stappler LLC <admin@stappler.dev>
3 :
4 : Permission is hereby granted, free of charge, to any person obtaining a copy
5 : of this software and associated documentation files (the "Software"), to deal
6 : in the Software without restriction, including without limitation the rights
7 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : copies of the Software, and to permit persons to whom the Software is
9 : furnished to do so, subject to the following conditions:
10 :
11 : The above copyright notice and this permission notice shall be included in
12 : all copies or substantial portions of the Software.
13 :
14 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : THE SOFTWARE.
21 : **/
22 :
23 : #ifndef CORE_WASM_SPWASM_H_
24 : #define CORE_WASM_SPWASM_H_
25 :
26 : #include "SPMemory.h"
27 : #include "SPRef.h"
28 :
29 : #include <typeindex>
30 :
31 : #include "wamr/wasm_export.h"
32 :
33 : namespace stappler::wasm {
34 :
35 : using namespace mem_std;
36 :
37 : class ModuleInstance;
38 : class ExecFunction;
39 :
40 : struct ListOutput {
41 : uint32_t ptr;
42 : uint32_t len;
43 :
44 : template <typename T>
45 : void setData(ModuleInstance *, const T *, size_t count);
46 : };
47 :
48 : class Runtime final {
49 : public:
50 : static Runtime *getInstance();
51 :
52 : ~Runtime();
53 :
54 : protected:
55 : struct Data;
56 :
57 : Runtime();
58 :
59 : Data *_data;
60 : };
61 :
62 : struct NativeModule {
63 : NativeModule(StringView, NativeSymbol *, size_t count);
64 : ~NativeModule();
65 :
66 : String name;
67 : NativeSymbol *symbols;
68 : size_t symbolsCount;
69 : };
70 :
71 : class Module final : public Ref {
72 : public:
73 : virtual ~Module();
74 :
75 : bool init(StringView name, BytesView);
76 : bool init(StringView name, Bytes &&);
77 : bool init(StringView name, FilePath);
78 :
79 25 : StringView getName() const { return _name; }
80 25 : wasm_module_t getModule() const { return _module; }
81 :
82 : protected:
83 : String _name;
84 : Bytes _data;
85 : Runtime *_runtime = nullptr;
86 : wasm_module_t _module = nullptr;
87 : };
88 :
89 : class ModuleInstance final : public Ref {
90 : public:
91 : static constexpr uint32_t InvalidHandle = maxOf<uint32_t>();
92 :
93 : virtual ~ModuleInstance();
94 :
95 : bool init(Module *, uint32_t stackSize = 16_KiB, uint32_t heapSize = 16_KiB);
96 :
97 25 : Module * getModule() const { return _module; }
98 550 : wasm_module_inst_t getInstance() const { return _inst; }
99 :
100 : void *appToNative(uint32_t offset) const;
101 : uint32_t nativeToApp(void *ptr) const;
102 :
103 : uint32_t allocate(uint32_t size, void ** = nullptr);
104 : uint32_t reallocate(uint32_t ptr, uint32_t size, void ** = nullptr);
105 :
106 : void free(uint32_t ptr);
107 :
108 : Rc<ExecFunction> lookup(StringView);
109 :
110 : template <typename T>
111 : uint32_t addHandle(T *, Function<void()> &&dtor = nullptr);
112 :
113 : template <typename T>
114 : uint32_t getHandle(T *) const;
115 :
116 : template <typename T = void>
117 : T *getObject(uint32_t) const;
118 :
119 : uint32_t getHandle(void *) const;
120 :
121 : void removeHandle(uint32_t);
122 : void removeObject(void *);
123 :
124 : protected:
125 : uint32_t addHandleObject(void *, std::type_index &&, Function<void()> &&);
126 : uint32_t getHandleObject(void *, const std::type_index &) const;
127 : void *getObjectHandle(uint32_t, const std::type_index &) const;
128 :
129 : struct HandleSlot {
130 : void *object = nullptr;
131 : std::type_index type = std::type_index(typeid(void));
132 : uint32_t index;
133 : uint32_t nextIndex = InvalidHandle;
134 : Function<void()> destructor;
135 : };
136 :
137 : Rc<Module> _module;
138 : wasm_module_inst_t _inst = nullptr;
139 : wasm_function_inst_t _finalize = nullptr;
140 : wasm_function_inst_t _realloc = nullptr;
141 :
142 : uint32_t _selfHandle = 0;
143 : uint32_t _freeHandleSlot = InvalidHandle;
144 : Vector<HandleSlot> _handles;
145 : HashMap<void *, uint32_t> _objects;
146 : };
147 :
148 : class ExecEnv final : public Ref {
149 : public:
150 : static ExecEnv *get(wasm_exec_env_t);
151 :
152 : virtual ~ExecEnv();
153 :
154 : bool init(ModuleInstance *, uint32_t stackSize = 16_KiB);
155 : bool init(ModuleInstance *, wasm_exec_env_t);
156 :
157 25 : wasm_exec_env_t getEnv() const { return _env; }
158 325 : ModuleInstance *getInstance() const { return _instance; }
159 :
160 : template <typename T = void>
161 375 : auto appToNative(uint32_t offset) const -> T * {
162 375 : return reinterpret_cast<T *>(_instance->appToNative(offset));
163 : }
164 : uint32_t nativeToApp(void *ptr) const;
165 :
166 : template <typename T = void>
167 200 : uint32_t allocate(uint32_t size, T **ptr = nullptr) {
168 200 : return _instance->allocate(size, reinterpret_cast<void **>(ptr));
169 : }
170 :
171 25 : void free(uint32_t ptr) {
172 25 : _instance->free(ptr);
173 25 : }
174 :
175 : bool callIndirect(uint32_t, uint32_t argc, uint32_t argv[]);
176 :
177 : protected:
178 : Rc<ModuleInstance> _instance;
179 : wasm_exec_env_t _env = nullptr;
180 : bool _isSingleton = false;
181 : };
182 :
183 : class ExecFunction final : public Ref {
184 : public:
185 : static constexpr uint32_t StaticArgumentsLimit = 28;
186 : static constexpr uint32_t StaticResultsLimit = 4;
187 :
188 200 : virtual ~ExecFunction() = default;
189 :
190 : bool init(ModuleInstance *, StringView name);
191 :
192 25 : StringView getName() const { return _name; }
193 50 : wasm_function_inst_t getFunc() const { return _func; }
194 :
195 50 : uint32_t getNumArgs() const { return _nArgs; }
196 50 : uint32_t getNumResults() const { return _nResults; }
197 :
198 : SpanView<wasm_valkind_t> getArgs() const { return makeSpanView(_argTypesStatic, std::max(_nArgs, StaticArgumentsLimit)); }
199 : SpanView<wasm_valkind_t> getResults() const { return makeSpanView(_resultTypesStatic, std::max(_nResults, StaticResultsLimit)); }
200 :
201 : // use when statics are out of limit
202 : Vector<wasm_valkind_t> getArgsFull() const;
203 : Vector<wasm_valkind_t> getResultsFull() const;
204 :
205 : bool call(ExecEnv *, SpanView<wasm_val_t> args = SpanView<wasm_val_t>(), VectorAdapter<wasm_val_t> *results = nullptr) const;
206 :
207 : wasm_val_t call1(ExecEnv *, SpanView<wasm_val_t> args = SpanView<wasm_val_t>()) const;
208 :
209 : protected:
210 : String _name;
211 : wasm_function_inst_t _func = nullptr;
212 : Rc<ModuleInstance> _inst;
213 : uint32_t _nArgs = 0;
214 : uint32_t _nResults = 0;
215 : wasm_valkind_t _resultTypesStatic[StaticResultsLimit] = { 0 };
216 : wasm_valkind_t _argTypesStatic[StaticArgumentsLimit] = { 0 };
217 : };
218 :
219 0 : inline wasm_val_t MakeValue(uint32_t val) {
220 : wasm_val_t ret;
221 0 : ret.kind = WASM_I32;
222 0 : ret.of.i32 = val;
223 0 : return ret;
224 : }
225 :
226 : inline wasm_val_t MakeValue(int32_t val) {
227 : wasm_val_t ret;
228 : ret.kind = WASM_I32;
229 : ret.of.i32 = val;
230 : return ret;
231 : }
232 :
233 : inline wasm_val_t MakeValue(uint64_t val) {
234 : wasm_val_t ret;
235 : ret.kind = WASM_I64;
236 : ret.of.i64 = val;
237 : return ret;
238 : }
239 :
240 : inline wasm_val_t MakeValue(int64_t val) {
241 : wasm_val_t ret;
242 : ret.kind = WASM_I64;
243 : ret.of.i64 = val;
244 : return ret;
245 : }
246 :
247 : inline wasm_val_t MakeValue(float val) {
248 : wasm_val_t ret;
249 : ret.kind = WASM_F32;
250 : ret.of.f32 = val;
251 : return ret;
252 : }
253 :
254 : inline wasm_val_t MakeValue(double val) {
255 : wasm_val_t ret;
256 : ret.kind = WASM_F64;
257 : ret.of.f64 = val;
258 : return ret;
259 : }
260 :
261 : template <typename T>
262 125 : void ListOutput::setData(ModuleInstance *inst, const T *data, size_t count) {
263 125 : uint8_t *buf = nullptr;
264 125 : ptr = inst->allocate(count * sizeof(T), (void **)&buf);
265 125 : len = count;
266 125 : memcpy(buf, data, count * sizeof(T));
267 125 : }
268 :
269 : template <typename T>
270 100 : uint32_t ModuleInstance::addHandle(T *obj, Function<void()> &&dtor) {
271 : using Type = typename std::remove_reference<typename std::remove_cv<T>::type>::type;
272 100 : return addHandleObject((Type *)obj, std::type_index(typeid(Type)), move(dtor));
273 : }
274 :
275 : template <typename T>
276 : uint32_t ModuleInstance::getHandle(T *obj) const {
277 : return getHandleObject(obj, std::type_index(typeid(typename std::remove_reference<typename std::remove_cv<T>::type>::type)));
278 : }
279 :
280 : template <typename T>
281 275 : T *ModuleInstance::getObject(uint32_t idx) const {
282 275 : return reinterpret_cast<T *>(getObjectHandle(idx, std::type_index(typeid(typename std::remove_reference<typename std::remove_cv<T>::type>::type))));
283 : }
284 :
285 : }
286 :
287 : #endif /* CORE_WASM_SPWASM_H_ */
|