1 | /**************************************************************************/ |
2 | /* gdscript_vm.cpp */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #include "gdscript.h" |
32 | #include "gdscript_function.h" |
33 | #include "gdscript_lambda_callable.h" |
34 | |
35 | #include "core/core_string_names.h" |
36 | #include "core/os/os.h" |
37 | |
38 | #ifdef DEBUG_ENABLED |
39 | static String _get_element_type(Variant::Type builtin_type, const StringName &native_type, const Ref<Script> &script_type) { |
40 | if (script_type.is_valid() && script_type->is_valid()) { |
41 | return GDScript::debug_get_script_name(script_type); |
42 | } else if (native_type != StringName()) { |
43 | return native_type.operator String(); |
44 | } else { |
45 | return Variant::get_type_name(builtin_type); |
46 | } |
47 | } |
48 | |
49 | static String _get_var_type(const Variant *p_var) { |
50 | String basestr; |
51 | |
52 | if (p_var->get_type() == Variant::OBJECT) { |
53 | bool was_freed; |
54 | Object *bobj = p_var->get_validated_object_with_check(was_freed); |
55 | if (!bobj) { |
56 | if (was_freed) { |
57 | basestr = "previously freed" ; |
58 | } else { |
59 | basestr = "null instance" ; |
60 | } |
61 | } else { |
62 | if (bobj->is_class_ptr(GDScriptNativeClass::get_class_ptr_static())) { |
63 | basestr = Object::cast_to<GDScriptNativeClass>(bobj)->get_name(); |
64 | } else { |
65 | basestr = bobj->get_class(); |
66 | if (bobj->get_script_instance()) { |
67 | basestr += " (" + GDScript::debug_get_script_name(bobj->get_script_instance()->get_script()) + ")" ; |
68 | } |
69 | } |
70 | } |
71 | |
72 | } else { |
73 | if (p_var->get_type() == Variant::ARRAY) { |
74 | basestr = "Array" ; |
75 | const Array *p_array = VariantInternal::get_array(p_var); |
76 | Variant::Type builtin_type = (Variant::Type)p_array->get_typed_builtin(); |
77 | if (builtin_type != Variant::NIL) { |
78 | basestr += "[" + _get_element_type(builtin_type, p_array->get_typed_class_name(), p_array->get_typed_script()) + "]" ; |
79 | } |
80 | } else { |
81 | basestr = Variant::get_type_name(p_var->get_type()); |
82 | } |
83 | } |
84 | |
85 | return basestr; |
86 | } |
87 | #endif // DEBUG_ENABLED |
88 | |
89 | Variant GDScriptFunction::_get_default_variant_for_data_type(const GDScriptDataType &p_data_type) { |
90 | if (p_data_type.kind == GDScriptDataType::BUILTIN) { |
91 | if (p_data_type.builtin_type == Variant::ARRAY) { |
92 | Array array; |
93 | // Typed array. |
94 | if (p_data_type.has_container_element_type()) { |
95 | const GDScriptDataType &element_type = p_data_type.get_container_element_type(); |
96 | array.set_typed(element_type.builtin_type, element_type.native_type, element_type.script_type); |
97 | } |
98 | |
99 | return array; |
100 | } else { |
101 | Callable::CallError ce; |
102 | Variant variant; |
103 | Variant::construct(p_data_type.builtin_type, variant, nullptr, 0, ce); |
104 | |
105 | ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, Variant()); |
106 | |
107 | return variant; |
108 | } |
109 | } |
110 | |
111 | return Variant(); |
112 | } |
113 | |
114 | String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const String &p_where, const Variant **argptrs) const { |
115 | String err_text; |
116 | |
117 | if (p_err.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) { |
118 | int errorarg = p_err.argument; |
119 | ERR_FAIL_COND_V_MSG(errorarg < 0 || argptrs[errorarg] == nullptr, "GDScript bug (please report): Invalid CallError argument index or null pointer." , "Invalid CallError argument index or null pointer." ); |
120 | // Handle the Object to Object case separately as we don't have further class details. |
121 | #ifdef DEBUG_ENABLED |
122 | if (p_err.expected == Variant::OBJECT && argptrs[errorarg]->get_type() == p_err.expected) { |
123 | err_text = "Invalid type in " + p_where + ". The Object-derived class of argument " + itos(errorarg + 1) + " (" + _get_var_type(argptrs[errorarg]) + ") is not a subclass of the expected argument class." ; |
124 | } else if (p_err.expected == Variant::ARRAY && argptrs[errorarg]->get_type() == p_err.expected) { |
125 | err_text = "Invalid type in " + p_where + ". The array of argument " + itos(errorarg + 1) + " (" + _get_var_type(argptrs[errorarg]) + ") does not have the same element type as the expected typed array argument." ; |
126 | } else |
127 | #endif // DEBUG_ENABLED |
128 | { |
129 | err_text = "Invalid type in " + p_where + ". Cannot convert argument " + itos(errorarg + 1) + " from " + Variant::get_type_name(argptrs[errorarg]->get_type()) + " to " + Variant::get_type_name(Variant::Type(p_err.expected)) + "." ; |
130 | } |
131 | } else if (p_err.error == Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) { |
132 | err_text = "Invalid call to " + p_where + ". Expected " + itos(p_err.expected) + " arguments." ; |
133 | } else if (p_err.error == Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) { |
134 | err_text = "Invalid call to " + p_where + ". Expected " + itos(p_err.expected) + " arguments." ; |
135 | } else if (p_err.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) { |
136 | err_text = "Invalid call. Nonexistent " + p_where + "." ; |
137 | } else if (p_err.error == Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL) { |
138 | err_text = "Attempt to call " + p_where + " on a null instance." ; |
139 | } else if (p_err.error == Callable::CallError::CALL_ERROR_METHOD_NOT_CONST) { |
140 | err_text = "Attempt to call " + p_where + " on a const instance." ; |
141 | } else { |
142 | err_text = "Bug, call error: #" + itos(p_err.error); |
143 | } |
144 | |
145 | return err_text; |
146 | } |
147 | |
148 | void (*type_init_function_table[])(Variant *) = { |
149 | nullptr, // NIL (shouldn't be called). |
150 | &VariantInitializer<bool>::init, // BOOL. |
151 | &VariantInitializer<int64_t>::init, // INT. |
152 | &VariantInitializer<double>::init, // FLOAT. |
153 | &VariantInitializer<String>::init, // STRING. |
154 | &VariantInitializer<Vector2>::init, // VECTOR2. |
155 | &VariantInitializer<Vector2i>::init, // VECTOR2I. |
156 | &VariantInitializer<Rect2>::init, // RECT2. |
157 | &VariantInitializer<Rect2i>::init, // RECT2I. |
158 | &VariantInitializer<Vector3>::init, // VECTOR3. |
159 | &VariantInitializer<Vector3i>::init, // VECTOR3I. |
160 | &VariantInitializer<Transform2D>::init, // TRANSFORM2D. |
161 | &VariantInitializer<Vector4>::init, // VECTOR4. |
162 | &VariantInitializer<Vector4i>::init, // VECTOR4I. |
163 | &VariantInitializer<Plane>::init, // PLANE. |
164 | &VariantInitializer<Quaternion>::init, // QUATERNION. |
165 | &VariantInitializer<AABB>::init, // AABB. |
166 | &VariantInitializer<Basis>::init, // BASIS. |
167 | &VariantInitializer<Transform3D>::init, // TRANSFORM3D. |
168 | &VariantInitializer<Projection>::init, // PROJECTION. |
169 | &VariantInitializer<Color>::init, // COLOR. |
170 | &VariantInitializer<StringName>::init, // STRING_NAME. |
171 | &VariantInitializer<NodePath>::init, // NODE_PATH. |
172 | &VariantInitializer<RID>::init, // RID. |
173 | &VariantInitializer<Object *>::init, // OBJECT. |
174 | &VariantInitializer<Callable>::init, // CALLABLE. |
175 | &VariantInitializer<Signal>::init, // SIGNAL. |
176 | &VariantInitializer<Dictionary>::init, // DICTIONARY. |
177 | &VariantInitializer<Array>::init, // ARRAY. |
178 | &VariantInitializer<PackedByteArray>::init, // PACKED_BYTE_ARRAY. |
179 | &VariantInitializer<PackedInt32Array>::init, // PACKED_INT32_ARRAY. |
180 | &VariantInitializer<PackedInt64Array>::init, // PACKED_INT64_ARRAY. |
181 | &VariantInitializer<PackedFloat32Array>::init, // PACKED_FLOAT32_ARRAY. |
182 | &VariantInitializer<PackedFloat64Array>::init, // PACKED_FLOAT64_ARRAY. |
183 | &VariantInitializer<PackedStringArray>::init, // PACKED_STRING_ARRAY. |
184 | &VariantInitializer<PackedVector2Array>::init, // PACKED_VECTOR2_ARRAY. |
185 | &VariantInitializer<PackedVector3Array>::init, // PACKED_VECTOR3_ARRAY. |
186 | &VariantInitializer<PackedColorArray>::init, // PACKED_COLOR_ARRAY. |
187 | }; |
188 | |
189 | #if defined(__GNUC__) |
190 | #define OPCODES_TABLE \ |
191 | static const void *switch_table_ops[] = { \ |
192 | &&OPCODE_OPERATOR, \ |
193 | &&OPCODE_OPERATOR_VALIDATED, \ |
194 | &&OPCODE_TYPE_TEST_BUILTIN, \ |
195 | &&OPCODE_TYPE_TEST_ARRAY, \ |
196 | &&OPCODE_TYPE_TEST_NATIVE, \ |
197 | &&OPCODE_TYPE_TEST_SCRIPT, \ |
198 | &&OPCODE_SET_KEYED, \ |
199 | &&OPCODE_SET_KEYED_VALIDATED, \ |
200 | &&OPCODE_SET_INDEXED_VALIDATED, \ |
201 | &&OPCODE_GET_KEYED, \ |
202 | &&OPCODE_GET_KEYED_VALIDATED, \ |
203 | &&OPCODE_GET_INDEXED_VALIDATED, \ |
204 | &&OPCODE_SET_NAMED, \ |
205 | &&OPCODE_SET_NAMED_VALIDATED, \ |
206 | &&OPCODE_GET_NAMED, \ |
207 | &&OPCODE_GET_NAMED_VALIDATED, \ |
208 | &&OPCODE_SET_MEMBER, \ |
209 | &&OPCODE_GET_MEMBER, \ |
210 | &&OPCODE_SET_STATIC_VARIABLE, \ |
211 | &&OPCODE_GET_STATIC_VARIABLE, \ |
212 | &&OPCODE_ASSIGN, \ |
213 | &&OPCODE_ASSIGN_TRUE, \ |
214 | &&OPCODE_ASSIGN_FALSE, \ |
215 | &&OPCODE_ASSIGN_TYPED_BUILTIN, \ |
216 | &&OPCODE_ASSIGN_TYPED_ARRAY, \ |
217 | &&OPCODE_ASSIGN_TYPED_NATIVE, \ |
218 | &&OPCODE_ASSIGN_TYPED_SCRIPT, \ |
219 | &&OPCODE_CAST_TO_BUILTIN, \ |
220 | &&OPCODE_CAST_TO_NATIVE, \ |
221 | &&OPCODE_CAST_TO_SCRIPT, \ |
222 | &&OPCODE_CONSTRUCT, \ |
223 | &&OPCODE_CONSTRUCT_VALIDATED, \ |
224 | &&OPCODE_CONSTRUCT_ARRAY, \ |
225 | &&OPCODE_CONSTRUCT_TYPED_ARRAY, \ |
226 | &&OPCODE_CONSTRUCT_DICTIONARY, \ |
227 | &&OPCODE_CALL, \ |
228 | &&OPCODE_CALL_RETURN, \ |
229 | &&OPCODE_CALL_ASYNC, \ |
230 | &&OPCODE_CALL_UTILITY, \ |
231 | &&OPCODE_CALL_UTILITY_VALIDATED, \ |
232 | &&OPCODE_CALL_GDSCRIPT_UTILITY, \ |
233 | &&OPCODE_CALL_BUILTIN_TYPE_VALIDATED, \ |
234 | &&OPCODE_CALL_SELF_BASE, \ |
235 | &&OPCODE_CALL_METHOD_BIND, \ |
236 | &&OPCODE_CALL_METHOD_BIND_RET, \ |
237 | &&OPCODE_CALL_BUILTIN_STATIC, \ |
238 | &&OPCODE_CALL_NATIVE_STATIC, \ |
239 | &&OPCODE_CALL_PTRCALL_NO_RETURN, \ |
240 | &&OPCODE_CALL_PTRCALL_BOOL, \ |
241 | &&OPCODE_CALL_PTRCALL_INT, \ |
242 | &&OPCODE_CALL_PTRCALL_FLOAT, \ |
243 | &&OPCODE_CALL_PTRCALL_STRING, \ |
244 | &&OPCODE_CALL_PTRCALL_VECTOR2, \ |
245 | &&OPCODE_CALL_PTRCALL_VECTOR2I, \ |
246 | &&OPCODE_CALL_PTRCALL_RECT2, \ |
247 | &&OPCODE_CALL_PTRCALL_RECT2I, \ |
248 | &&OPCODE_CALL_PTRCALL_VECTOR3, \ |
249 | &&OPCODE_CALL_PTRCALL_VECTOR3I, \ |
250 | &&OPCODE_CALL_PTRCALL_TRANSFORM2D, \ |
251 | &&OPCODE_CALL_PTRCALL_VECTOR4, \ |
252 | &&OPCODE_CALL_PTRCALL_VECTOR4I, \ |
253 | &&OPCODE_CALL_PTRCALL_PLANE, \ |
254 | &&OPCODE_CALL_PTRCALL_QUATERNION, \ |
255 | &&OPCODE_CALL_PTRCALL_AABB, \ |
256 | &&OPCODE_CALL_PTRCALL_BASIS, \ |
257 | &&OPCODE_CALL_PTRCALL_TRANSFORM3D, \ |
258 | &&OPCODE_CALL_PTRCALL_PROJECTION, \ |
259 | &&OPCODE_CALL_PTRCALL_COLOR, \ |
260 | &&OPCODE_CALL_PTRCALL_STRING_NAME, \ |
261 | &&OPCODE_CALL_PTRCALL_NODE_PATH, \ |
262 | &&OPCODE_CALL_PTRCALL_RID, \ |
263 | &&OPCODE_CALL_PTRCALL_OBJECT, \ |
264 | &&OPCODE_CALL_PTRCALL_CALLABLE, \ |
265 | &&OPCODE_CALL_PTRCALL_SIGNAL, \ |
266 | &&OPCODE_CALL_PTRCALL_DICTIONARY, \ |
267 | &&OPCODE_CALL_PTRCALL_ARRAY, \ |
268 | &&OPCODE_CALL_PTRCALL_PACKED_BYTE_ARRAY, \ |
269 | &&OPCODE_CALL_PTRCALL_PACKED_INT32_ARRAY, \ |
270 | &&OPCODE_CALL_PTRCALL_PACKED_INT64_ARRAY, \ |
271 | &&OPCODE_CALL_PTRCALL_PACKED_FLOAT32_ARRAY, \ |
272 | &&OPCODE_CALL_PTRCALL_PACKED_FLOAT64_ARRAY, \ |
273 | &&OPCODE_CALL_PTRCALL_PACKED_STRING_ARRAY, \ |
274 | &&OPCODE_CALL_PTRCALL_PACKED_VECTOR2_ARRAY, \ |
275 | &&OPCODE_CALL_PTRCALL_PACKED_VECTOR3_ARRAY, \ |
276 | &&OPCODE_CALL_PTRCALL_PACKED_COLOR_ARRAY, \ |
277 | &&OPCODE_AWAIT, \ |
278 | &&OPCODE_AWAIT_RESUME, \ |
279 | &&OPCODE_CREATE_LAMBDA, \ |
280 | &&OPCODE_CREATE_SELF_LAMBDA, \ |
281 | &&OPCODE_JUMP, \ |
282 | &&OPCODE_JUMP_IF, \ |
283 | &&OPCODE_JUMP_IF_NOT, \ |
284 | &&OPCODE_JUMP_TO_DEF_ARGUMENT, \ |
285 | &&OPCODE_JUMP_IF_SHARED, \ |
286 | &&OPCODE_RETURN, \ |
287 | &&OPCODE_RETURN_TYPED_BUILTIN, \ |
288 | &&OPCODE_RETURN_TYPED_ARRAY, \ |
289 | &&OPCODE_RETURN_TYPED_NATIVE, \ |
290 | &&OPCODE_RETURN_TYPED_SCRIPT, \ |
291 | &&OPCODE_ITERATE_BEGIN, \ |
292 | &&OPCODE_ITERATE_BEGIN_INT, \ |
293 | &&OPCODE_ITERATE_BEGIN_FLOAT, \ |
294 | &&OPCODE_ITERATE_BEGIN_VECTOR2, \ |
295 | &&OPCODE_ITERATE_BEGIN_VECTOR2I, \ |
296 | &&OPCODE_ITERATE_BEGIN_VECTOR3, \ |
297 | &&OPCODE_ITERATE_BEGIN_VECTOR3I, \ |
298 | &&OPCODE_ITERATE_BEGIN_STRING, \ |
299 | &&OPCODE_ITERATE_BEGIN_DICTIONARY, \ |
300 | &&OPCODE_ITERATE_BEGIN_ARRAY, \ |
301 | &&OPCODE_ITERATE_BEGIN_PACKED_BYTE_ARRAY, \ |
302 | &&OPCODE_ITERATE_BEGIN_PACKED_INT32_ARRAY, \ |
303 | &&OPCODE_ITERATE_BEGIN_PACKED_INT64_ARRAY, \ |
304 | &&OPCODE_ITERATE_BEGIN_PACKED_FLOAT32_ARRAY, \ |
305 | &&OPCODE_ITERATE_BEGIN_PACKED_FLOAT64_ARRAY, \ |
306 | &&OPCODE_ITERATE_BEGIN_PACKED_STRING_ARRAY, \ |
307 | &&OPCODE_ITERATE_BEGIN_PACKED_VECTOR2_ARRAY, \ |
308 | &&OPCODE_ITERATE_BEGIN_PACKED_VECTOR3_ARRAY, \ |
309 | &&OPCODE_ITERATE_BEGIN_PACKED_COLOR_ARRAY, \ |
310 | &&OPCODE_ITERATE_BEGIN_OBJECT, \ |
311 | &&OPCODE_ITERATE, \ |
312 | &&OPCODE_ITERATE_INT, \ |
313 | &&OPCODE_ITERATE_FLOAT, \ |
314 | &&OPCODE_ITERATE_VECTOR2, \ |
315 | &&OPCODE_ITERATE_VECTOR2I, \ |
316 | &&OPCODE_ITERATE_VECTOR3, \ |
317 | &&OPCODE_ITERATE_VECTOR3I, \ |
318 | &&OPCODE_ITERATE_STRING, \ |
319 | &&OPCODE_ITERATE_DICTIONARY, \ |
320 | &&OPCODE_ITERATE_ARRAY, \ |
321 | &&OPCODE_ITERATE_PACKED_BYTE_ARRAY, \ |
322 | &&OPCODE_ITERATE_PACKED_INT32_ARRAY, \ |
323 | &&OPCODE_ITERATE_PACKED_INT64_ARRAY, \ |
324 | &&OPCODE_ITERATE_PACKED_FLOAT32_ARRAY, \ |
325 | &&OPCODE_ITERATE_PACKED_FLOAT64_ARRAY, \ |
326 | &&OPCODE_ITERATE_PACKED_STRING_ARRAY, \ |
327 | &&OPCODE_ITERATE_PACKED_VECTOR2_ARRAY, \ |
328 | &&OPCODE_ITERATE_PACKED_VECTOR3_ARRAY, \ |
329 | &&OPCODE_ITERATE_PACKED_COLOR_ARRAY, \ |
330 | &&OPCODE_ITERATE_OBJECT, \ |
331 | &&OPCODE_STORE_GLOBAL, \ |
332 | &&OPCODE_STORE_NAMED_GLOBAL, \ |
333 | &&OPCODE_TYPE_ADJUST_BOOL, \ |
334 | &&OPCODE_TYPE_ADJUST_INT, \ |
335 | &&OPCODE_TYPE_ADJUST_FLOAT, \ |
336 | &&OPCODE_TYPE_ADJUST_STRING, \ |
337 | &&OPCODE_TYPE_ADJUST_VECTOR2, \ |
338 | &&OPCODE_TYPE_ADJUST_VECTOR2I, \ |
339 | &&OPCODE_TYPE_ADJUST_RECT2, \ |
340 | &&OPCODE_TYPE_ADJUST_RECT2I, \ |
341 | &&OPCODE_TYPE_ADJUST_VECTOR3, \ |
342 | &&OPCODE_TYPE_ADJUST_VECTOR3I, \ |
343 | &&OPCODE_TYPE_ADJUST_TRANSFORM2D, \ |
344 | &&OPCODE_TYPE_ADJUST_VECTOR4, \ |
345 | &&OPCODE_TYPE_ADJUST_VECTOR4I, \ |
346 | &&OPCODE_TYPE_ADJUST_PLANE, \ |
347 | &&OPCODE_TYPE_ADJUST_QUATERNION, \ |
348 | &&OPCODE_TYPE_ADJUST_AABB, \ |
349 | &&OPCODE_TYPE_ADJUST_BASIS, \ |
350 | &&OPCODE_TYPE_ADJUST_TRANSFORM3D, \ |
351 | &&OPCODE_TYPE_ADJUST_PROJECTION, \ |
352 | &&OPCODE_TYPE_ADJUST_COLOR, \ |
353 | &&OPCODE_TYPE_ADJUST_STRING_NAME, \ |
354 | &&OPCODE_TYPE_ADJUST_NODE_PATH, \ |
355 | &&OPCODE_TYPE_ADJUST_RID, \ |
356 | &&OPCODE_TYPE_ADJUST_OBJECT, \ |
357 | &&OPCODE_TYPE_ADJUST_CALLABLE, \ |
358 | &&OPCODE_TYPE_ADJUST_SIGNAL, \ |
359 | &&OPCODE_TYPE_ADJUST_DICTIONARY, \ |
360 | &&OPCODE_TYPE_ADJUST_ARRAY, \ |
361 | &&OPCODE_TYPE_ADJUST_PACKED_BYTE_ARRAY, \ |
362 | &&OPCODE_TYPE_ADJUST_PACKED_INT32_ARRAY, \ |
363 | &&OPCODE_TYPE_ADJUST_PACKED_INT64_ARRAY, \ |
364 | &&OPCODE_TYPE_ADJUST_PACKED_FLOAT32_ARRAY, \ |
365 | &&OPCODE_TYPE_ADJUST_PACKED_FLOAT64_ARRAY, \ |
366 | &&OPCODE_TYPE_ADJUST_PACKED_STRING_ARRAY, \ |
367 | &&OPCODE_TYPE_ADJUST_PACKED_VECTOR2_ARRAY, \ |
368 | &&OPCODE_TYPE_ADJUST_PACKED_VECTOR3_ARRAY, \ |
369 | &&OPCODE_TYPE_ADJUST_PACKED_COLOR_ARRAY, \ |
370 | &&OPCODE_ASSERT, \ |
371 | &&OPCODE_BREAKPOINT, \ |
372 | &&OPCODE_LINE, \ |
373 | &&OPCODE_END \ |
374 | }; \ |
375 | static_assert((sizeof(switch_table_ops) / sizeof(switch_table_ops[0]) == (OPCODE_END + 1)), "Opcodes in jump table aren't the same as opcodes in enum."); |
376 | |
377 | #define OPCODE(m_op) \ |
378 | m_op: |
379 | #define OPCODE_WHILE(m_test) |
380 | #define OPCODES_END \ |
381 | OPSEXIT: |
382 | #define OPCODES_OUT \ |
383 | OPSOUT: |
384 | #define OPCODE_SWITCH(m_test) goto *switch_table_ops[m_test]; |
385 | #ifdef DEBUG_ENABLED |
386 | #define DISPATCH_OPCODE \ |
387 | last_opcode = _code_ptr[ip]; \ |
388 | goto *switch_table_ops[last_opcode] |
389 | #else |
390 | #define DISPATCH_OPCODE goto *switch_table_ops[_code_ptr[ip]] |
391 | #endif |
392 | #define OPCODE_BREAK goto OPSEXIT |
393 | #define OPCODE_OUT goto OPSOUT |
394 | #else |
395 | #define OPCODES_TABLE |
396 | #define OPCODE(m_op) case m_op: |
397 | #define OPCODE_WHILE(m_test) while (m_test) |
398 | #define OPCODES_END |
399 | #define OPCODES_OUT |
400 | #define DISPATCH_OPCODE continue |
401 | #define OPCODE_SWITCH(m_test) switch (m_test) |
402 | #define OPCODE_BREAK break |
403 | #define OPCODE_OUT break |
404 | #endif |
405 | |
406 | // Helpers for VariantInternal methods in macros. |
407 | #define OP_GET_BOOL get_bool |
408 | #define OP_GET_INT get_int |
409 | #define OP_GET_FLOAT get_float |
410 | #define OP_GET_VECTOR2 get_vector2 |
411 | #define OP_GET_VECTOR2I get_vector2i |
412 | #define OP_GET_VECTOR3 get_vector3 |
413 | #define OP_GET_VECTOR3I get_vector3i |
414 | #define OP_GET_RECT2 get_rect2 |
415 | #define OP_GET_VECTOR4 get_vector4 |
416 | #define OP_GET_VECTOR4I get_vector4i |
417 | #define OP_GET_RECT2I get_rect2i |
418 | #define OP_GET_QUATERNION get_quaternion |
419 | #define OP_GET_COLOR get_color |
420 | #define OP_GET_STRING get_string |
421 | #define OP_GET_STRING_NAME get_string_name |
422 | #define OP_GET_NODE_PATH get_node_path |
423 | #define OP_GET_CALLABLE get_callable |
424 | #define OP_GET_SIGNAL get_signal |
425 | #define OP_GET_ARRAY get_array |
426 | #define OP_GET_DICTIONARY get_dictionary |
427 | #define OP_GET_PACKED_BYTE_ARRAY get_byte_array |
428 | #define OP_GET_PACKED_INT32_ARRAY get_int32_array |
429 | #define OP_GET_PACKED_INT64_ARRAY get_int64_array |
430 | #define OP_GET_PACKED_FLOAT32_ARRAY get_float32_array |
431 | #define OP_GET_PACKED_FLOAT64_ARRAY get_float64_array |
432 | #define OP_GET_PACKED_STRING_ARRAY get_string_array |
433 | #define OP_GET_PACKED_VECTOR2_ARRAY get_vector2_array |
434 | #define OP_GET_PACKED_VECTOR3_ARRAY get_vector3_array |
435 | #define OP_GET_PACKED_COLOR_ARRAY get_color_array |
436 | #define OP_GET_TRANSFORM3D get_transform |
437 | #define OP_GET_TRANSFORM2D get_transform2d |
438 | #define OP_GET_PROJECTION get_projection |
439 | #define OP_GET_PLANE get_plane |
440 | #define OP_GET_AABB get_aabb |
441 | #define OP_GET_BASIS get_basis |
442 | #define OP_GET_RID get_rid |
443 | |
444 | #define METHOD_CALL_ON_NULL_VALUE_ERROR(method_pointer) "Cannot call method '" + (method_pointer)->get_name() + "' on a null value." |
445 | #define METHOD_CALL_ON_FREED_INSTANCE_ERROR(method_pointer) "Cannot call method '" + (method_pointer)->get_name() + "' on a previously freed instance." |
446 | |
447 | Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_args, int p_argcount, Callable::CallError &r_err, CallState *p_state) { |
448 | OPCODES_TABLE; |
449 | |
450 | if (!_code_ptr) { |
451 | return _get_default_variant_for_data_type(return_type); |
452 | } |
453 | |
454 | r_err.error = Callable::CallError::CALL_OK; |
455 | |
456 | static thread_local int call_depth = 0; |
457 | if (unlikely(++call_depth > MAX_CALL_DEPTH)) { |
458 | call_depth--; |
459 | #ifdef DEBUG_ENABLED |
460 | String err_file; |
461 | if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && !p_instance->script->path.is_empty()) { |
462 | err_file = p_instance->script->path; |
463 | } else if (_script) { |
464 | err_file = _script->path; |
465 | } |
466 | if (err_file.is_empty()) { |
467 | err_file = "<built-in>" ; |
468 | } |
469 | String err_func = name; |
470 | if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && p_instance->script->local_name != StringName()) { |
471 | err_func = p_instance->script->local_name.operator String() + "." + err_func; |
472 | } |
473 | int err_line = _initial_line; |
474 | const char *err_text = "Stack overflow. Check for infinite recursion in your script." ; |
475 | if (!GDScriptLanguage::get_singleton()->debug_break(err_text, false)) { |
476 | // Debugger break did not happen. |
477 | _err_print_error(err_func.utf8().get_data(), err_file.utf8().get_data(), err_line, err_text, false, ERR_HANDLER_SCRIPT); |
478 | } |
479 | #endif |
480 | return _get_default_variant_for_data_type(return_type); |
481 | } |
482 | |
483 | Variant retvalue; |
484 | Variant *stack = nullptr; |
485 | Variant **instruction_args = nullptr; |
486 | const void **call_args_ptr = nullptr; |
487 | int defarg = 0; |
488 | |
489 | #ifdef DEBUG_ENABLED |
490 | |
491 | //GDScriptLanguage::get_singleton()->calls++; |
492 | |
493 | #endif |
494 | |
495 | uint32_t alloca_size = 0; |
496 | GDScript *script; |
497 | int ip = 0; |
498 | int line = _initial_line; |
499 | |
500 | if (p_state) { |
501 | //use existing (supplied) state (awaited) |
502 | stack = (Variant *)p_state->stack.ptr(); |
503 | instruction_args = (Variant **)&p_state->stack.ptr()[sizeof(Variant) * p_state->stack_size]; //ptr() to avoid bounds check |
504 | line = p_state->line; |
505 | ip = p_state->ip; |
506 | alloca_size = p_state->stack.size(); |
507 | script = p_state->script; |
508 | p_instance = p_state->instance; |
509 | defarg = p_state->defarg; |
510 | |
511 | } else { |
512 | if (p_argcount != _argument_count) { |
513 | if (p_argcount > _argument_count) { |
514 | r_err.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; |
515 | r_err.expected = _argument_count; |
516 | |
517 | call_depth--; |
518 | return _get_default_variant_for_data_type(return_type); |
519 | } else if (p_argcount < _argument_count - _default_arg_count) { |
520 | r_err.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; |
521 | r_err.expected = _argument_count - _default_arg_count; |
522 | call_depth--; |
523 | return _get_default_variant_for_data_type(return_type); |
524 | } else { |
525 | defarg = _argument_count - p_argcount; |
526 | } |
527 | } |
528 | |
529 | // Add 3 here for self, class, and nil. |
530 | alloca_size = sizeof(Variant *) * 3 + sizeof(Variant *) * _instruction_args_size + sizeof(Variant) * _stack_size; |
531 | |
532 | uint8_t *aptr = (uint8_t *)alloca(alloca_size); |
533 | stack = (Variant *)aptr; |
534 | |
535 | for (int i = 0; i < p_argcount; i++) { |
536 | if (!argument_types[i].has_type) { |
537 | memnew_placement(&stack[i + 3], Variant(*p_args[i])); |
538 | continue; |
539 | } |
540 | // If types already match, don't call Variant::construct(). Constructors of some types |
541 | // (e.g. packed arrays) do copies, whereas they pass by reference when inside a Variant. |
542 | if (argument_types[i].is_type(*p_args[i], false)) { |
543 | memnew_placement(&stack[i + 3], Variant(*p_args[i])); |
544 | continue; |
545 | } |
546 | if (!argument_types[i].is_type(*p_args[i], true)) { |
547 | r_err.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; |
548 | r_err.argument = i; |
549 | r_err.expected = argument_types[i].builtin_type; |
550 | call_depth--; |
551 | return _get_default_variant_for_data_type(return_type); |
552 | } |
553 | if (argument_types[i].kind == GDScriptDataType::BUILTIN) { |
554 | Variant arg; |
555 | Variant::construct(argument_types[i].builtin_type, arg, &p_args[i], 1, r_err); |
556 | memnew_placement(&stack[i + 3], Variant(arg)); |
557 | } else { |
558 | memnew_placement(&stack[i + 3], Variant(*p_args[i])); |
559 | } |
560 | } |
561 | for (int i = p_argcount + 3; i < _stack_size; i++) { |
562 | memnew_placement(&stack[i], Variant); |
563 | } |
564 | |
565 | if (_instruction_args_size) { |
566 | instruction_args = (Variant **)&aptr[sizeof(Variant) * _stack_size]; |
567 | } else { |
568 | instruction_args = nullptr; |
569 | } |
570 | |
571 | for (const KeyValue<int, Variant::Type> &E : temporary_slots) { |
572 | type_init_function_table[E.value](&stack[E.key]); |
573 | } |
574 | } |
575 | |
576 | if (_ptrcall_args_size) { |
577 | call_args_ptr = (const void **)alloca(_ptrcall_args_size * sizeof(void *)); |
578 | } else { |
579 | call_args_ptr = nullptr; |
580 | } |
581 | |
582 | if (p_instance) { |
583 | memnew_placement(&stack[ADDR_STACK_SELF], Variant(p_instance->owner)); |
584 | script = p_instance->script.ptr(); |
585 | } else { |
586 | memnew_placement(&stack[ADDR_STACK_SELF], Variant); |
587 | script = _script; |
588 | } |
589 | memnew_placement(&stack[ADDR_STACK_CLASS], Variant(script)); |
590 | memnew_placement(&stack[ADDR_STACK_NIL], Variant); |
591 | |
592 | String err_text; |
593 | |
594 | #ifdef DEBUG_ENABLED |
595 | |
596 | if (EngineDebugger::is_active()) { |
597 | GDScriptLanguage::get_singleton()->enter_function(p_instance, this, stack, &ip, &line); |
598 | } |
599 | |
600 | #define GD_ERR_BREAK(m_cond) \ |
601 | { \ |
602 | if (unlikely(m_cond)) { \ |
603 | _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Breaking..:"); \ |
604 | OPCODE_BREAK; \ |
605 | } \ |
606 | } |
607 | |
608 | #define CHECK_SPACE(m_space) \ |
609 | GD_ERR_BREAK((ip + m_space) > _code_size) |
610 | |
611 | #define GET_VARIANT_PTR(m_v, m_code_ofs) \ |
612 | Variant *m_v; \ |
613 | { \ |
614 | int |
---|