Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/modules/gdscript/gdscript_vm.cpp
20938 views
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/os/os.h"
36
#include "core/profiling/profiling.h"
37
38
#ifdef DEBUG_ENABLED
39
40
static bool _profile_count_as_native(const Object *p_base_obj, const StringName &p_methodname) {
41
if (!p_base_obj) {
42
return false;
43
}
44
StringName cname = p_base_obj->get_class_name();
45
if ((p_methodname == "new" && cname == "GDScript") || p_methodname == "call") {
46
return false;
47
}
48
return ClassDB::class_exists(cname) && ClassDB::has_method(cname, p_methodname, false);
49
}
50
51
static String _get_element_type(Variant::Type builtin_type, const StringName &native_type, const Ref<Script> &script_type) {
52
if (script_type.is_valid() && script_type->is_valid()) {
53
return GDScript::debug_get_script_name(script_type);
54
} else if (native_type != StringName()) {
55
return native_type.operator String();
56
} else {
57
return Variant::get_type_name(builtin_type);
58
}
59
}
60
61
static String _get_var_type(const Variant *p_var) {
62
String basestr;
63
64
if (p_var->get_type() == Variant::OBJECT) {
65
bool was_freed;
66
Object *bobj = p_var->get_validated_object_with_check(was_freed);
67
if (!bobj) {
68
if (was_freed) {
69
basestr = "previously freed";
70
} else {
71
basestr = "null instance";
72
}
73
} else {
74
if (bobj->is_class_ptr(GDScriptNativeClass::get_class_ptr_static())) {
75
basestr = Object::cast_to<GDScriptNativeClass>(bobj)->get_name();
76
} else {
77
basestr = bobj->get_class();
78
if (bobj->get_script_instance()) {
79
basestr += " (" + GDScript::debug_get_script_name(bobj->get_script_instance()->get_script()) + ")";
80
}
81
}
82
}
83
84
} else {
85
if (p_var->get_type() == Variant::ARRAY) {
86
basestr = "Array";
87
const Array *p_array = VariantInternal::get_array(p_var);
88
if (p_array->is_typed()) {
89
basestr += "[" + _get_element_type((Variant::Type)p_array->get_typed_builtin(), p_array->get_typed_class_name(), p_array->get_typed_script()) + "]";
90
}
91
} else if (p_var->get_type() == Variant::DICTIONARY) {
92
basestr = "Dictionary";
93
const Dictionary *p_dictionary = VariantInternal::get_dictionary(p_var);
94
if (p_dictionary->is_typed()) {
95
basestr += "[" + _get_element_type((Variant::Type)p_dictionary->get_typed_key_builtin(), p_dictionary->get_typed_key_class_name(), p_dictionary->get_typed_key_script()) +
96
", " + _get_element_type((Variant::Type)p_dictionary->get_typed_value_builtin(), p_dictionary->get_typed_value_class_name(), p_dictionary->get_typed_value_script()) + "]";
97
}
98
} else {
99
basestr = Variant::get_type_name(p_var->get_type());
100
}
101
}
102
103
return basestr;
104
}
105
106
void GDScriptFunction::_profile_native_call(uint64_t p_t_taken, const String &p_func_name, const String &p_instance_class_name) {
107
HashMap<String, Profile::NativeProfile>::Iterator inner_prof = profile.native_calls.find(p_func_name);
108
if (inner_prof) {
109
inner_prof->value.call_count += 1;
110
} else {
111
String sig = vformat("%s::0::%s%s%s", get_script()->get_script_path(), p_instance_class_name, p_instance_class_name.is_empty() ? "" : ".", p_func_name);
112
inner_prof = profile.native_calls.insert(p_func_name, Profile::NativeProfile{ 1, 0, sig });
113
}
114
inner_prof->value.total_time += p_t_taken;
115
}
116
117
#endif // DEBUG_ENABLED
118
119
Variant GDScriptFunction::_get_default_variant_for_data_type(const GDScriptDataType &p_data_type) {
120
if (p_data_type.kind == GDScriptDataType::BUILTIN) {
121
if (p_data_type.builtin_type == Variant::ARRAY) {
122
Array array;
123
// Typed array.
124
if (p_data_type.has_container_element_type(0)) {
125
const GDScriptDataType &element_type = p_data_type.get_container_element_type(0);
126
array.set_typed(element_type.builtin_type, element_type.native_type, element_type.script_type);
127
}
128
129
return array;
130
} else if (p_data_type.builtin_type == Variant::DICTIONARY) {
131
Dictionary dict;
132
// Typed dictionary.
133
if (p_data_type.has_container_element_types()) {
134
const GDScriptDataType &key_type = p_data_type.get_container_element_type_or_variant(0);
135
const GDScriptDataType &value_type = p_data_type.get_container_element_type_or_variant(1);
136
dict.set_typed(key_type.builtin_type, key_type.native_type, key_type.script_type, value_type.builtin_type, value_type.native_type, value_type.script_type);
137
}
138
139
return dict;
140
} else {
141
Callable::CallError ce;
142
Variant variant;
143
Variant::construct(p_data_type.builtin_type, variant, nullptr, 0, ce);
144
145
ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, Variant());
146
147
return variant;
148
}
149
}
150
151
return Variant();
152
}
153
154
String GDScriptFunction::_get_call_error(const String &p_where, const Variant **p_argptrs, int p_argcount, const Variant &p_ret, const Callable::CallError &p_err) const {
155
switch (p_err.error) {
156
case Callable::CallError::CALL_OK:
157
return String();
158
case Callable::CallError::CALL_ERROR_INVALID_METHOD:
159
if (p_ret.get_type() == Variant::STRING && !p_ret.operator String().is_empty()) {
160
return "Invalid call " + p_where + ": " + p_ret.operator String();
161
}
162
return "Invalid call. Nonexistent " + p_where + ".";
163
case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT:
164
ERR_FAIL_INDEX_V_MSG(p_err.argument, p_argcount, "Bug: Invalid call error argument index.", "Bug: Invalid call error argument index.");
165
ERR_FAIL_NULL_V_MSG(p_argptrs[p_err.argument], "Bug: Argument is null pointer.", "Bug: Argument is null pointer.");
166
// Handle the Object to Object case separately as we don't have further class details.
167
#ifdef DEBUG_ENABLED
168
if (p_err.expected == Variant::OBJECT && p_argptrs[p_err.argument]->get_type() == p_err.expected) {
169
return "Invalid type in " + p_where + ". The Object-derived class of argument " + itos(p_err.argument + 1) + " (" + _get_var_type(p_argptrs[p_err.argument]) + ") is not a subclass of the expected argument class.";
170
}
171
if (p_err.expected == Variant::ARRAY && p_argptrs[p_err.argument]->get_type() == p_err.expected) {
172
return "Invalid type in " + p_where + ". The array of argument " + itos(p_err.argument + 1) + " (" + _get_var_type(p_argptrs[p_err.argument]) + ") does not have the same element type as the expected typed array argument.";
173
}
174
if (p_err.expected == Variant::DICTIONARY && p_argptrs[p_err.argument]->get_type() == p_err.expected) {
175
return "Invalid type in " + p_where + ". The dictionary of argument " + itos(p_err.argument + 1) + " (" + _get_var_type(p_argptrs[p_err.argument]) + ") does not have the same element type as the expected typed dictionary argument.";
176
}
177
#endif // DEBUG_ENABLED
178
return "Invalid type in " + p_where + ". Cannot convert argument " + itos(p_err.argument + 1) + " from " + Variant::get_type_name(p_argptrs[p_err.argument]->get_type()) + " to " + Variant::get_type_name(Variant::Type(p_err.expected)) + ".";
179
case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS:
180
case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS:
181
return "Invalid call to " + p_where + ". Expected " + itos(p_err.expected) + " argument(s).";
182
case Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL:
183
return "Attempt to call " + p_where + " on a null instance.";
184
case Callable::CallError::CALL_ERROR_METHOD_NOT_CONST:
185
return "Attempt to call " + p_where + " on a const instance.";
186
}
187
return "Bug: Invalid call error code " + itos(p_err.error) + ".";
188
}
189
190
String GDScriptFunction::_get_callable_call_error(const String &p_where, const Callable &p_callable, const Variant **p_argptrs, int p_argcount, const Variant &p_ret, const Callable::CallError &p_err) const {
191
Vector<Variant> binds;
192
p_callable.get_bound_arguments_ref(binds);
193
194
int args_unbound = p_callable.get_unbound_arguments_count();
195
196
if (p_argcount - args_unbound < 0) {
197
return "Callable unbinds " + itos(args_unbound) + " arguments, but called with " + itos(p_argcount);
198
} else {
199
Vector<const Variant *> argptrs;
200
argptrs.resize(p_argcount - args_unbound + binds.size());
201
for (int i = 0; i < p_argcount - args_unbound; i++) {
202
argptrs.write[i] = p_argptrs[i];
203
}
204
for (int i = 0; i < binds.size(); i++) {
205
argptrs.write[i + p_argcount - args_unbound] = &binds[i];
206
}
207
return _get_call_error(p_where, (const Variant **)argptrs.ptr(), argptrs.size(), p_ret, p_err);
208
}
209
}
210
211
void (*type_init_function_table[])(Variant *) = {
212
nullptr, // NIL (shouldn't be called).
213
&VariantInitializer<bool>::init, // BOOL.
214
&VariantInitializer<int64_t>::init, // INT.
215
&VariantInitializer<double>::init, // FLOAT.
216
&VariantInitializer<String>::init, // STRING.
217
&VariantInitializer<Vector2>::init, // VECTOR2.
218
&VariantInitializer<Vector2i>::init, // VECTOR2I.
219
&VariantInitializer<Rect2>::init, // RECT2.
220
&VariantInitializer<Rect2i>::init, // RECT2I.
221
&VariantInitializer<Vector3>::init, // VECTOR3.
222
&VariantInitializer<Vector3i>::init, // VECTOR3I.
223
&VariantInitializer<Transform2D>::init, // TRANSFORM2D.
224
&VariantInitializer<Vector4>::init, // VECTOR4.
225
&VariantInitializer<Vector4i>::init, // VECTOR4I.
226
&VariantInitializer<Plane>::init, // PLANE.
227
&VariantInitializer<Quaternion>::init, // QUATERNION.
228
&VariantInitializer<AABB>::init, // AABB.
229
&VariantInitializer<Basis>::init, // BASIS.
230
&VariantInitializer<Transform3D>::init, // TRANSFORM3D.
231
&VariantInitializer<Projection>::init, // PROJECTION.
232
&VariantInitializer<Color>::init, // COLOR.
233
&VariantInitializer<StringName>::init, // STRING_NAME.
234
&VariantInitializer<NodePath>::init, // NODE_PATH.
235
&VariantInitializer<RID>::init, // RID.
236
&VariantInitializer<Object *>::init, // OBJECT.
237
&VariantInitializer<Callable>::init, // CALLABLE.
238
&VariantInitializer<Signal>::init, // SIGNAL.
239
&VariantInitializer<Dictionary>::init, // DICTIONARY.
240
&VariantInitializer<Array>::init, // ARRAY.
241
&VariantInitializer<PackedByteArray>::init, // PACKED_BYTE_ARRAY.
242
&VariantInitializer<PackedInt32Array>::init, // PACKED_INT32_ARRAY.
243
&VariantInitializer<PackedInt64Array>::init, // PACKED_INT64_ARRAY.
244
&VariantInitializer<PackedFloat32Array>::init, // PACKED_FLOAT32_ARRAY.
245
&VariantInitializer<PackedFloat64Array>::init, // PACKED_FLOAT64_ARRAY.
246
&VariantInitializer<PackedStringArray>::init, // PACKED_STRING_ARRAY.
247
&VariantInitializer<PackedVector2Array>::init, // PACKED_VECTOR2_ARRAY.
248
&VariantInitializer<PackedVector3Array>::init, // PACKED_VECTOR3_ARRAY.
249
&VariantInitializer<PackedColorArray>::init, // PACKED_COLOR_ARRAY.
250
&VariantInitializer<PackedVector4Array>::init, // PACKED_VECTOR4_ARRAY.
251
};
252
253
#if defined(__GNUC__) || defined(__clang__)
254
#define OPCODES_TABLE \
255
static const void *switch_table_ops[] = { \
256
&&OPCODE_OPERATOR, \
257
&&OPCODE_OPERATOR_VALIDATED, \
258
&&OPCODE_TYPE_TEST_BUILTIN, \
259
&&OPCODE_TYPE_TEST_ARRAY, \
260
&&OPCODE_TYPE_TEST_DICTIONARY, \
261
&&OPCODE_TYPE_TEST_NATIVE, \
262
&&OPCODE_TYPE_TEST_SCRIPT, \
263
&&OPCODE_SET_KEYED, \
264
&&OPCODE_SET_KEYED_VALIDATED, \
265
&&OPCODE_SET_INDEXED_VALIDATED, \
266
&&OPCODE_GET_KEYED, \
267
&&OPCODE_GET_KEYED_VALIDATED, \
268
&&OPCODE_GET_INDEXED_VALIDATED, \
269
&&OPCODE_SET_NAMED, \
270
&&OPCODE_SET_NAMED_VALIDATED, \
271
&&OPCODE_GET_NAMED, \
272
&&OPCODE_GET_NAMED_VALIDATED, \
273
&&OPCODE_SET_MEMBER, \
274
&&OPCODE_GET_MEMBER, \
275
&&OPCODE_SET_STATIC_VARIABLE, \
276
&&OPCODE_GET_STATIC_VARIABLE, \
277
&&OPCODE_ASSIGN, \
278
&&OPCODE_ASSIGN_NULL, \
279
&&OPCODE_ASSIGN_TRUE, \
280
&&OPCODE_ASSIGN_FALSE, \
281
&&OPCODE_ASSIGN_TYPED_BUILTIN, \
282
&&OPCODE_ASSIGN_TYPED_ARRAY, \
283
&&OPCODE_ASSIGN_TYPED_DICTIONARY, \
284
&&OPCODE_ASSIGN_TYPED_NATIVE, \
285
&&OPCODE_ASSIGN_TYPED_SCRIPT, \
286
&&OPCODE_CAST_TO_BUILTIN, \
287
&&OPCODE_CAST_TO_NATIVE, \
288
&&OPCODE_CAST_TO_SCRIPT, \
289
&&OPCODE_CONSTRUCT, \
290
&&OPCODE_CONSTRUCT_VALIDATED, \
291
&&OPCODE_CONSTRUCT_ARRAY, \
292
&&OPCODE_CONSTRUCT_TYPED_ARRAY, \
293
&&OPCODE_CONSTRUCT_DICTIONARY, \
294
&&OPCODE_CONSTRUCT_TYPED_DICTIONARY, \
295
&&OPCODE_CALL, \
296
&&OPCODE_CALL_RETURN, \
297
&&OPCODE_CALL_ASYNC, \
298
&&OPCODE_CALL_UTILITY, \
299
&&OPCODE_CALL_UTILITY_VALIDATED, \
300
&&OPCODE_CALL_GDSCRIPT_UTILITY, \
301
&&OPCODE_CALL_BUILTIN_TYPE_VALIDATED, \
302
&&OPCODE_CALL_SELF_BASE, \
303
&&OPCODE_CALL_METHOD_BIND, \
304
&&OPCODE_CALL_METHOD_BIND_RET, \
305
&&OPCODE_CALL_BUILTIN_STATIC, \
306
&&OPCODE_CALL_NATIVE_STATIC, \
307
&&OPCODE_CALL_NATIVE_STATIC_VALIDATED_RETURN, \
308
&&OPCODE_CALL_NATIVE_STATIC_VALIDATED_NO_RETURN, \
309
&&OPCODE_CALL_METHOD_BIND_VALIDATED_RETURN, \
310
&&OPCODE_CALL_METHOD_BIND_VALIDATED_NO_RETURN, \
311
&&OPCODE_AWAIT, \
312
&&OPCODE_AWAIT_RESUME, \
313
&&OPCODE_CREATE_LAMBDA, \
314
&&OPCODE_CREATE_SELF_LAMBDA, \
315
&&OPCODE_JUMP, \
316
&&OPCODE_JUMP_IF, \
317
&&OPCODE_JUMP_IF_NOT, \
318
&&OPCODE_JUMP_TO_DEF_ARGUMENT, \
319
&&OPCODE_JUMP_IF_SHARED, \
320
&&OPCODE_RETURN, \
321
&&OPCODE_RETURN_TYPED_BUILTIN, \
322
&&OPCODE_RETURN_TYPED_ARRAY, \
323
&&OPCODE_RETURN_TYPED_DICTIONARY, \
324
&&OPCODE_RETURN_TYPED_NATIVE, \
325
&&OPCODE_RETURN_TYPED_SCRIPT, \
326
&&OPCODE_ITERATE_BEGIN, \
327
&&OPCODE_ITERATE_BEGIN_INT, \
328
&&OPCODE_ITERATE_BEGIN_FLOAT, \
329
&&OPCODE_ITERATE_BEGIN_VECTOR2, \
330
&&OPCODE_ITERATE_BEGIN_VECTOR2I, \
331
&&OPCODE_ITERATE_BEGIN_VECTOR3, \
332
&&OPCODE_ITERATE_BEGIN_VECTOR3I, \
333
&&OPCODE_ITERATE_BEGIN_STRING, \
334
&&OPCODE_ITERATE_BEGIN_DICTIONARY, \
335
&&OPCODE_ITERATE_BEGIN_ARRAY, \
336
&&OPCODE_ITERATE_BEGIN_PACKED_BYTE_ARRAY, \
337
&&OPCODE_ITERATE_BEGIN_PACKED_INT32_ARRAY, \
338
&&OPCODE_ITERATE_BEGIN_PACKED_INT64_ARRAY, \
339
&&OPCODE_ITERATE_BEGIN_PACKED_FLOAT32_ARRAY, \
340
&&OPCODE_ITERATE_BEGIN_PACKED_FLOAT64_ARRAY, \
341
&&OPCODE_ITERATE_BEGIN_PACKED_STRING_ARRAY, \
342
&&OPCODE_ITERATE_BEGIN_PACKED_VECTOR2_ARRAY, \
343
&&OPCODE_ITERATE_BEGIN_PACKED_VECTOR3_ARRAY, \
344
&&OPCODE_ITERATE_BEGIN_PACKED_COLOR_ARRAY, \
345
&&OPCODE_ITERATE_BEGIN_PACKED_VECTOR4_ARRAY, \
346
&&OPCODE_ITERATE_BEGIN_OBJECT, \
347
&&OPCODE_ITERATE_BEGIN_RANGE, \
348
&&OPCODE_ITERATE, \
349
&&OPCODE_ITERATE_INT, \
350
&&OPCODE_ITERATE_FLOAT, \
351
&&OPCODE_ITERATE_VECTOR2, \
352
&&OPCODE_ITERATE_VECTOR2I, \
353
&&OPCODE_ITERATE_VECTOR3, \
354
&&OPCODE_ITERATE_VECTOR3I, \
355
&&OPCODE_ITERATE_STRING, \
356
&&OPCODE_ITERATE_DICTIONARY, \
357
&&OPCODE_ITERATE_ARRAY, \
358
&&OPCODE_ITERATE_PACKED_BYTE_ARRAY, \
359
&&OPCODE_ITERATE_PACKED_INT32_ARRAY, \
360
&&OPCODE_ITERATE_PACKED_INT64_ARRAY, \
361
&&OPCODE_ITERATE_PACKED_FLOAT32_ARRAY, \
362
&&OPCODE_ITERATE_PACKED_FLOAT64_ARRAY, \
363
&&OPCODE_ITERATE_PACKED_STRING_ARRAY, \
364
&&OPCODE_ITERATE_PACKED_VECTOR2_ARRAY, \
365
&&OPCODE_ITERATE_PACKED_VECTOR3_ARRAY, \
366
&&OPCODE_ITERATE_PACKED_COLOR_ARRAY, \
367
&&OPCODE_ITERATE_PACKED_VECTOR4_ARRAY, \
368
&&OPCODE_ITERATE_OBJECT, \
369
&&OPCODE_ITERATE_RANGE, \
370
&&OPCODE_STORE_GLOBAL, \
371
&&OPCODE_STORE_NAMED_GLOBAL, \
372
&&OPCODE_TYPE_ADJUST_BOOL, \
373
&&OPCODE_TYPE_ADJUST_INT, \
374
&&OPCODE_TYPE_ADJUST_FLOAT, \
375
&&OPCODE_TYPE_ADJUST_STRING, \
376
&&OPCODE_TYPE_ADJUST_VECTOR2, \
377
&&OPCODE_TYPE_ADJUST_VECTOR2I, \
378
&&OPCODE_TYPE_ADJUST_RECT2, \
379
&&OPCODE_TYPE_ADJUST_RECT2I, \
380
&&OPCODE_TYPE_ADJUST_VECTOR3, \
381
&&OPCODE_TYPE_ADJUST_VECTOR3I, \
382
&&OPCODE_TYPE_ADJUST_TRANSFORM2D, \
383
&&OPCODE_TYPE_ADJUST_VECTOR4, \
384
&&OPCODE_TYPE_ADJUST_VECTOR4I, \
385
&&OPCODE_TYPE_ADJUST_PLANE, \
386
&&OPCODE_TYPE_ADJUST_QUATERNION, \
387
&&OPCODE_TYPE_ADJUST_AABB, \
388
&&OPCODE_TYPE_ADJUST_BASIS, \
389
&&OPCODE_TYPE_ADJUST_TRANSFORM3D, \
390
&&OPCODE_TYPE_ADJUST_PROJECTION, \
391
&&OPCODE_TYPE_ADJUST_COLOR, \
392
&&OPCODE_TYPE_ADJUST_STRING_NAME, \
393
&&OPCODE_TYPE_ADJUST_NODE_PATH, \
394
&&OPCODE_TYPE_ADJUST_RID, \
395
&&OPCODE_TYPE_ADJUST_OBJECT, \
396
&&OPCODE_TYPE_ADJUST_CALLABLE, \
397
&&OPCODE_TYPE_ADJUST_SIGNAL, \
398
&&OPCODE_TYPE_ADJUST_DICTIONARY, \
399
&&OPCODE_TYPE_ADJUST_ARRAY, \
400
&&OPCODE_TYPE_ADJUST_PACKED_BYTE_ARRAY, \
401
&&OPCODE_TYPE_ADJUST_PACKED_INT32_ARRAY, \
402
&&OPCODE_TYPE_ADJUST_PACKED_INT64_ARRAY, \
403
&&OPCODE_TYPE_ADJUST_PACKED_FLOAT32_ARRAY, \
404
&&OPCODE_TYPE_ADJUST_PACKED_FLOAT64_ARRAY, \
405
&&OPCODE_TYPE_ADJUST_PACKED_STRING_ARRAY, \
406
&&OPCODE_TYPE_ADJUST_PACKED_VECTOR2_ARRAY, \
407
&&OPCODE_TYPE_ADJUST_PACKED_VECTOR3_ARRAY, \
408
&&OPCODE_TYPE_ADJUST_PACKED_COLOR_ARRAY, \
409
&&OPCODE_TYPE_ADJUST_PACKED_VECTOR4_ARRAY, \
410
&&OPCODE_ASSERT, \
411
&&OPCODE_BREAKPOINT, \
412
&&OPCODE_LINE, \
413
&&OPCODE_END \
414
}; \
415
static_assert(std_size(switch_table_ops) == (OPCODE_END + 1), "Opcodes in jump table aren't the same as opcodes in enum.");
416
417
#define OPCODE(m_op) \
418
m_op:
419
#define OPCODE_WHILE(m_test)
420
#define OPCODES_END \
421
OPSEXIT:
422
#define OPCODES_OUT \
423
OPSOUT:
424
#define OPCODE_SWITCH(m_test) goto *switch_table_ops[m_test];
425
426
#ifdef DEBUG_ENABLED
427
#define DISPATCH_OPCODE \
428
last_opcode = _code_ptr[ip]; \
429
goto *switch_table_ops[last_opcode]
430
#else // !DEBUG_ENABLED
431
#define DISPATCH_OPCODE goto *switch_table_ops[_code_ptr[ip]]
432
#endif // DEBUG_ENABLED
433
434
#define OPCODE_BREAK goto OPSEXIT
435
#define OPCODE_OUT goto OPSOUT
436
#else // !(defined(__GNUC__) || defined(__clang__))
437
#define OPCODES_TABLE
438
#define OPCODE(m_op) case m_op:
439
#define OPCODE_WHILE(m_test) while (m_test)
440
#define OPCODES_END
441
#define OPCODES_OUT
442
#define DISPATCH_OPCODE continue
443
444
#ifdef _MSC_VER
445
#define OPCODE_SWITCH(m_test) \
446
__assume(m_test <= OPCODE_END); \
447
switch (m_test)
448
#else // !_MSC_VER
449
#define OPCODE_SWITCH(m_test) switch (m_test)
450
#endif // _MSC_VER
451
452
#define OPCODE_BREAK break
453
#define OPCODE_OUT break
454
#endif // defined(__GNUC__) || defined(__clang__)
455
456
// Helpers for VariantInternal methods in macros.
457
#define OP_GET_BOOL get_bool
458
#define OP_GET_INT get_int
459
#define OP_GET_FLOAT get_float
460
#define OP_GET_VECTOR2 get_vector2
461
#define OP_GET_VECTOR2I get_vector2i
462
#define OP_GET_VECTOR3 get_vector3
463
#define OP_GET_VECTOR3I get_vector3i
464
#define OP_GET_RECT2 get_rect2
465
#define OP_GET_VECTOR4 get_vector4
466
#define OP_GET_VECTOR4I get_vector4i
467
#define OP_GET_RECT2I get_rect2i
468
#define OP_GET_QUATERNION get_quaternion
469
#define OP_GET_COLOR get_color
470
#define OP_GET_STRING get_string
471
#define OP_GET_STRING_NAME get_string_name
472
#define OP_GET_NODE_PATH get_node_path
473
#define OP_GET_CALLABLE get_callable
474
#define OP_GET_SIGNAL get_signal
475
#define OP_GET_ARRAY get_array
476
#define OP_GET_DICTIONARY get_dictionary
477
#define OP_GET_PACKED_BYTE_ARRAY get_byte_array
478
#define OP_GET_PACKED_INT32_ARRAY get_int32_array
479
#define OP_GET_PACKED_INT64_ARRAY get_int64_array
480
#define OP_GET_PACKED_FLOAT32_ARRAY get_float32_array
481
#define OP_GET_PACKED_FLOAT64_ARRAY get_float64_array
482
#define OP_GET_PACKED_STRING_ARRAY get_string_array
483
#define OP_GET_PACKED_VECTOR2_ARRAY get_vector2_array
484
#define OP_GET_PACKED_VECTOR3_ARRAY get_vector3_array
485
#define OP_GET_PACKED_COLOR_ARRAY get_color_array
486
#define OP_GET_PACKED_VECTOR4_ARRAY get_vector4_array
487
#define OP_GET_TRANSFORM3D get_transform
488
#define OP_GET_TRANSFORM2D get_transform2d
489
#define OP_GET_PROJECTION get_projection
490
#define OP_GET_PLANE get_plane
491
#define OP_GET_AABB get_aabb
492
#define OP_GET_BASIS get_basis
493
#define OP_GET_RID get_rid
494
495
#define METHOD_CALL_ON_NULL_VALUE_ERROR(method_pointer) "Cannot call method '" + (method_pointer)->get_name() + "' on a null value."
496
#define METHOD_CALL_ON_FREED_INSTANCE_ERROR(method_pointer) "Cannot call method '" + (method_pointer)->get_name() + "' on a previously freed instance."
497
498
Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_args, int p_argcount, Callable::CallError &r_err, CallState *p_state) {
499
GodotProfileZoneScript(this, source, name, name, _initial_line);
500
501
OPCODES_TABLE;
502
503
if (!_code_ptr) {
504
return _get_default_variant_for_data_type(return_type);
505
}
506
507
r_err.error = Callable::CallError::CALL_OK;
508
509
static thread_local int call_depth = 0;
510
if (unlikely(++call_depth > MAX_CALL_DEPTH)) {
511
call_depth--;
512
#ifdef DEBUG_ENABLED
513
String err_file;
514
if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && !p_instance->script->path.is_empty()) {
515
err_file = p_instance->script->path;
516
} else if (_script) {
517
err_file = _script->path;
518
}
519
if (err_file.is_empty()) {
520
err_file = "<built-in>";
521
}
522
String err_func = name;
523
if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && p_instance->script->local_name != StringName()) {
524
err_func = p_instance->script->local_name.operator String() + "." + err_func;
525
}
526
int err_line = _initial_line;
527
const char *err_text = "Stack overflow. Check for infinite recursion in your script.";
528
_err_print_error(err_func.utf8().get_data(), err_file.utf8().get_data(), err_line, err_text, false, ERR_HANDLER_SCRIPT);
529
GDScriptLanguage::get_singleton()->debug_break(err_text, false);
530
#endif
531
return _get_default_variant_for_data_type(return_type);
532
}
533
534
Variant retvalue;
535
Variant *stack = nullptr;
536
Variant **instruction_args = nullptr;
537
int defarg = 0;
538
539
uint32_t alloca_size = 0;
540
GDScript *script;
541
int ip = 0;
542
int line = _initial_line;
543
544
if (p_state) {
545
//use existing (supplied) state (awaited)
546
stack = (Variant *)p_state->stack.ptr();
547
instruction_args = (Variant **)&p_state->stack.ptr()[sizeof(Variant) * p_state->stack_size]; //ptr() to avoid bounds check
548
line = p_state->line;
549
ip = p_state->ip;
550
alloca_size = p_state->stack.size();
551
script = p_state->script;
552
p_instance = p_state->instance;
553
defarg = p_state->defarg;
554
555
} else {
556
if (p_argcount != _argument_count) {
557
if (p_argcount > _argument_count) {
558
if (!is_vararg()) {
559
r_err.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
560
r_err.expected = _argument_count;
561
call_depth--;
562
return _get_default_variant_for_data_type(return_type);
563
}
564
} else if (p_argcount < _argument_count - _default_arg_count) {
565
r_err.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
566
r_err.expected = _argument_count - _default_arg_count;
567
call_depth--;
568
return _get_default_variant_for_data_type(return_type);
569
} else {
570
defarg = _argument_count - p_argcount;
571
}
572
}
573
574
alloca_size = sizeof(Variant *) * FIXED_ADDRESSES_MAX + sizeof(Variant *) * _instruction_args_size + sizeof(Variant) * _stack_size;
575
576
uint8_t *aptr = (uint8_t *)alloca(alloca_size);
577
stack = (Variant *)aptr;
578
579
const int non_vararg_arg_count = MIN(p_argcount, _argument_count);
580
for (int i = 0; i < non_vararg_arg_count; i++) {
581
if (!argument_types[i].has_type()) {
582
memnew_placement(&stack[i + FIXED_ADDRESSES_MAX], Variant(*p_args[i]));
583
continue;
584
}
585
// If types already match, don't call Variant::construct(). Constructors of some types
586
// (e.g. packed arrays) do copies, whereas they pass by reference when inside a Variant.
587
if (argument_types[i].is_type(*p_args[i], false)) {
588
memnew_placement(&stack[i + FIXED_ADDRESSES_MAX], Variant(*p_args[i]));
589
continue;
590
}
591
if (!argument_types[i].is_type(*p_args[i], true)) {
592
r_err.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
593
r_err.argument = i;
594
r_err.expected = argument_types[i].builtin_type;
595
call_depth--;
596
return _get_default_variant_for_data_type(return_type);
597
}
598
if (argument_types[i].kind == GDScriptDataType::BUILTIN) {
599
if (argument_types[i].builtin_type == Variant::DICTIONARY && argument_types[i].has_container_element_types()) {
600
const GDScriptDataType &arg_key_type = argument_types[i].get_container_element_type_or_variant(0);
601
const GDScriptDataType &arg_value_type = argument_types[i].get_container_element_type_or_variant(1);
602
Dictionary dict(p_args[i]->operator Dictionary(), arg_key_type.builtin_type, arg_key_type.native_type, arg_key_type.script_type, arg_value_type.builtin_type, arg_value_type.native_type, arg_value_type.script_type);
603
memnew_placement(&stack[i + FIXED_ADDRESSES_MAX], Variant(dict));
604
} else if (argument_types[i].builtin_type == Variant::ARRAY && argument_types[i].has_container_element_type(0)) {
605
const GDScriptDataType &arg_type = argument_types[i].container_element_types[0];
606
Array array(p_args[i]->operator Array(), arg_type.builtin_type, arg_type.native_type, arg_type.script_type);
607
memnew_placement(&stack[i + FIXED_ADDRESSES_MAX], Variant(array));
608
} else {
609
Variant variant;
610
Variant::construct(argument_types[i].builtin_type, variant, &p_args[i], 1, r_err);
611
if (unlikely(r_err.error)) {
612
r_err.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
613
r_err.argument = i;
614
r_err.expected = argument_types[i].builtin_type;
615
call_depth--;
616
return _get_default_variant_for_data_type(return_type);
617
}
618
memnew_placement(&stack[i + FIXED_ADDRESSES_MAX], Variant(variant));
619
}
620
} else {
621
memnew_placement(&stack[i + FIXED_ADDRESSES_MAX], Variant(*p_args[i]));
622
}
623
}
624
for (int i = non_vararg_arg_count + FIXED_ADDRESSES_MAX; i < _stack_size; i++) {
625
memnew_placement(&stack[i], Variant);
626
}
627
628
if (is_vararg()) {
629
Array vararg;
630
stack[_vararg_index] = vararg;
631
if (p_argcount > _argument_count) {
632
vararg.resize(p_argcount - _argument_count);
633
for (int i = 0; i < p_argcount - _argument_count; i++) {
634
vararg[i] = *p_args[i + _argument_count];
635
}
636
}
637
}
638
639
if (_instruction_args_size) {
640
instruction_args = (Variant **)&aptr[sizeof(Variant) * _stack_size];
641
} else {
642
instruction_args = nullptr;
643
}
644
645
for (const KeyValue<int, Variant::Type> &E : temporary_slots) {
646
type_init_function_table[E.value](&stack[E.key]);
647
}
648
}
649
650
if (p_instance) {
651
memnew_placement(&stack[ADDR_STACK_SELF], Variant(p_instance->owner));
652
script = p_instance->script.ptr();
653
} else {
654
memnew_placement(&stack[ADDR_STACK_SELF], Variant);
655
script = _script;
656
}
657
memnew_placement(&stack[ADDR_STACK_CLASS], Variant(script));
658
memnew_placement(&stack[ADDR_STACK_NIL], Variant);
659
660
String err_text;
661
662
GDScriptLanguage::CallLevel call_level;
663
GDScriptLanguage::get_singleton()->enter_function(&call_level, p_instance, this, stack, &ip, &line);
664
665
#ifdef DEBUG_ENABLED
666
#define GD_ERR_BREAK(m_cond) \
667
{ \
668
if (unlikely(m_cond)) { \
669
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Breaking..:"); \
670
OPCODE_BREAK; \
671
} \
672
}
673
674
#define CHECK_SPACE(m_space) \
675
GD_ERR_BREAK((ip + m_space) > _code_size)
676
677
#define GET_VARIANT_PTR(m_v, m_code_ofs) \
678
Variant *m_v; \
679
{ \
680
int address = _code_ptr[ip + 1 + (m_code_ofs)]; \
681
int address_type = (address & ADDR_TYPE_MASK) >> ADDR_BITS; \
682
if (unlikely(address_type < 0 || address_type >= ADDR_TYPE_MAX)) { \
683
err_text = "Bad address type."; \
684
OPCODE_BREAK; \
685
} \
686
int address_index = address & ADDR_MASK; \
687
if (unlikely(address_index < 0 || address_index >= variant_address_limits[address_type])) { \
688
if (address_type == ADDR_TYPE_MEMBER && !p_instance) { \
689
err_text = "Cannot access member without instance."; \
690
} else { \
691
err_text = "Bad address index."; \
692
} \
693
OPCODE_BREAK; \
694
} \
695
m_v = &variant_addresses[address_type][address_index]; \
696
if (unlikely(!m_v)) \
697
OPCODE_BREAK; \
698
}
699
700
#else // !DEBUG_ENABLED
701
#define GD_ERR_BREAK(m_cond)
702
#define CHECK_SPACE(m_space)
703
704
#define GET_VARIANT_PTR(m_v, m_code_ofs) \
705
Variant *m_v; \
706
{ \
707
int address = _code_ptr[ip + 1 + (m_code_ofs)]; \
708
m_v = &variant_addresses[(address & ADDR_TYPE_MASK) >> ADDR_BITS][address & ADDR_MASK]; \
709
if (unlikely(!m_v)) \
710
OPCODE_BREAK; \
711
}
712
713
#endif // DEBUG_ENABLED
714
715
#define LOAD_INSTRUCTION_ARGS \
716
int instr_arg_count = _code_ptr[ip + 1]; \
717
for (int i = 0; i < instr_arg_count; i++) { \
718
GET_VARIANT_PTR(v, i + 1); \
719
instruction_args[i] = v; \
720
} \
721
ip += 1; // Offset to skip instruction argcount.
722
723
#define GET_INSTRUCTION_ARG(m_v, m_idx) \
724
Variant *m_v = instruction_args[m_idx]
725
726
#ifdef DEBUG_ENABLED
727
uint64_t function_start_time = 0;
728
uint64_t function_call_time = 0;
729
730
if (GDScriptLanguage::get_singleton()->profiling) {
731
function_start_time = OS::get_singleton()->get_ticks_usec();
732
function_call_time = 0;
733
profile.call_count.increment();
734
profile.frame_call_count.increment();
735
}
736
bool exit_ok = false;
737
int variant_address_limits[ADDR_TYPE_MAX] = { _stack_size, _constant_count, p_instance ? (int)p_instance->members.size() : 0 };
738
#endif
739
740
bool awaited = false;
741
Variant *variant_addresses[ADDR_TYPE_MAX] = { stack, _constants_ptr, p_instance ? p_instance->members.ptrw() : nullptr };
742
743
#ifdef DEBUG_ENABLED
744
OPCODE_WHILE(ip < _code_size) {
745
int last_opcode = _code_ptr[ip];
746
#else
747
OPCODE_WHILE(true) {
748
#endif
749
750
OPCODE_SWITCH(_code_ptr[ip]) {
751
OPCODE(OPCODE_OPERATOR) {
752
constexpr int _pointer_size = sizeof(Variant::ValidatedOperatorEvaluator) / sizeof(*_code_ptr);
753
CHECK_SPACE(7 + _pointer_size);
754
755
bool valid;
756
Variant::Operator op = (Variant::Operator)_code_ptr[ip + 4];
757
GD_ERR_BREAK(op >= Variant::OP_MAX);
758
759
GET_VARIANT_PTR(a, 0);
760
GET_VARIANT_PTR(b, 1);
761
GET_VARIANT_PTR(dst, 2);
762
// Compute signatures (types of operands) so it can be optimized when matching.
763
uint32_t op_signature = _code_ptr[ip + 5];
764
uint32_t actual_signature = (a->get_type() << 8) | (b->get_type());
765
766
#ifdef DEBUG_ENABLED
767
if (op == Variant::OP_DIVIDE || op == Variant::OP_MODULE) {
768
// Don't optimize division and modulo since there's not check for division by zero with validated calls.
769
op_signature = 0xFFFF;
770
_code_ptr[ip + 5] = op_signature;
771
}
772
#endif
773
774
// Check if this is the first run. If so, store the current signature for the optimized path.
775
if (unlikely(op_signature == 0)) {
776
static Mutex initializer_mutex;
777
initializer_mutex.lock();
778
Variant::Type a_type = (Variant::Type)((actual_signature >> 8) & 0xFF);
779
Variant::Type b_type = (Variant::Type)(actual_signature & 0xFF);
780
781
Variant::ValidatedOperatorEvaluator op_func = Variant::get_validated_operator_evaluator(op, a_type, b_type);
782
783
if (unlikely(!op_func)) {
784
#ifdef DEBUG_ENABLED
785
err_text = "Invalid operands '" + Variant::get_type_name(a->get_type()) + "' and '" + Variant::get_type_name(b->get_type()) + "' in operator '" + Variant::get_operator_name(op) + "'.";
786
#endif
787
initializer_mutex.unlock();
788
OPCODE_BREAK;
789
} else {
790
Variant::Type ret_type = Variant::get_operator_return_type(op, a_type, b_type);
791
VariantInternal::initialize(dst, ret_type);
792
op_func(a, b, dst);
793
794
// Check again in case another thread already set it.
795
if (_code_ptr[ip + 5] == 0) {
796
_code_ptr[ip + 5] = actual_signature;
797
_code_ptr[ip + 6] = static_cast<int>(ret_type);
798
Variant::ValidatedOperatorEvaluator *tmp = reinterpret_cast<Variant::ValidatedOperatorEvaluator *>(&_code_ptr[ip + 7]);
799
*tmp = op_func;
800
}
801
}
802
initializer_mutex.unlock();
803
} else if (likely(op_signature == actual_signature)) {
804
// If the signature matches, we can use the optimized path.
805
Variant::Type ret_type = static_cast<Variant::Type>(_code_ptr[ip + 6]);
806
Variant::ValidatedOperatorEvaluator op_func = *reinterpret_cast<Variant::ValidatedOperatorEvaluator *>(&_code_ptr[ip + 7]);
807
808
// Make sure the return value has the correct type.
809
VariantInternal::initialize(dst, ret_type);
810
op_func(a, b, dst);
811
} else {
812
// If the signature doesn't match, we have to use the slow path.
813
#ifdef DEBUG_ENABLED
814
815
Variant ret;
816
Variant::evaluate(op, *a, *b, ret, valid);
817
#else
818
Variant::evaluate(op, *a, *b, *dst, valid);
819
#endif
820
#ifdef DEBUG_ENABLED
821
if (!valid) {
822
if (ret.get_type() == Variant::STRING) {
823
//return a string when invalid with the error
824
err_text = ret;
825
err_text += " in operator '" + Variant::get_operator_name(op) + "'.";
826
} else {
827
err_text = "Invalid operands '" + Variant::get_type_name(a->get_type()) + "' and '" + Variant::get_type_name(b->get_type()) + "' in operator '" + Variant::get_operator_name(op) + "'.";
828
}
829
OPCODE_BREAK;
830
}
831
*dst = ret;
832
#endif
833
}
834
ip += 7 + _pointer_size;
835
}
836
DISPATCH_OPCODE;
837
838
OPCODE(OPCODE_OPERATOR_VALIDATED) {
839
CHECK_SPACE(5);
840
841
int operator_idx = _code_ptr[ip + 4];
842
GD_ERR_BREAK(operator_idx < 0 || operator_idx >= _operator_funcs_count);
843
Variant::ValidatedOperatorEvaluator operator_func = _operator_funcs_ptr[operator_idx];
844
845
GET_VARIANT_PTR(a, 0);
846
GET_VARIANT_PTR(b, 1);
847
GET_VARIANT_PTR(dst, 2);
848
849
operator_func(a, b, dst);
850
851
ip += 5;
852
}
853
DISPATCH_OPCODE;
854
855
OPCODE(OPCODE_TYPE_TEST_BUILTIN) {
856
CHECK_SPACE(4);
857
858
GET_VARIANT_PTR(dst, 0);
859
GET_VARIANT_PTR(value, 1);
860
861
Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + 3];
862
GD_ERR_BREAK(builtin_type < 0 || builtin_type >= Variant::VARIANT_MAX);
863
864
*dst = value->get_type() == builtin_type;
865
ip += 4;
866
}
867
DISPATCH_OPCODE;
868
869
OPCODE(OPCODE_TYPE_TEST_ARRAY) {
870
CHECK_SPACE(6);
871
872
GET_VARIANT_PTR(dst, 0);
873
GET_VARIANT_PTR(value, 1);
874
875
GET_VARIANT_PTR(script_type, 2);
876
Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + 4];
877
int native_type_idx = _code_ptr[ip + 5];
878
GD_ERR_BREAK(native_type_idx < 0 || native_type_idx >= _global_names_count);
879
const StringName native_type = _global_names_ptr[native_type_idx];
880
881
bool result = false;
882
if (value->get_type() == Variant::ARRAY) {
883
Array *array = VariantInternal::get_array(value);
884
result = array->get_typed_builtin() == ((uint32_t)builtin_type) && array->get_typed_class_name() == native_type && array->get_typed_script() == *script_type;
885
}
886
887
*dst = result;
888
ip += 6;
889
}
890
DISPATCH_OPCODE;
891
892
OPCODE(OPCODE_TYPE_TEST_DICTIONARY) {
893
CHECK_SPACE(9);
894
895
GET_VARIANT_PTR(dst, 0);
896
GET_VARIANT_PTR(value, 1);
897
898
GET_VARIANT_PTR(key_script_type, 2);
899
Variant::Type key_builtin_type = (Variant::Type)_code_ptr[ip + 5];
900
int key_native_type_idx = _code_ptr[ip + 6];
901
GD_ERR_BREAK(key_native_type_idx < 0 || key_native_type_idx >= _global_names_count);
902
const StringName key_native_type = _global_names_ptr[key_native_type_idx];
903
904
GET_VARIANT_PTR(value_script_type, 3);
905
Variant::Type value_builtin_type = (Variant::Type)_code_ptr[ip + 7];
906
int value_native_type_idx = _code_ptr[ip + 8];
907
GD_ERR_BREAK(value_native_type_idx < 0 || value_native_type_idx >= _global_names_count);
908
const StringName value_native_type = _global_names_ptr[value_native_type_idx];
909
910
bool result = false;
911
if (value->get_type() == Variant::DICTIONARY) {
912
Dictionary *dictionary = VariantInternal::get_dictionary(value);
913
result = dictionary->get_typed_key_builtin() == ((uint32_t)key_builtin_type) && dictionary->get_typed_key_class_name() == key_native_type && dictionary->get_typed_key_script() == *key_script_type &&
914
dictionary->get_typed_value_builtin() == ((uint32_t)value_builtin_type) && dictionary->get_typed_value_class_name() == value_native_type && dictionary->get_typed_value_script() == *value_script_type;
915
}
916
917
*dst = result;
918
ip += 9;
919
}
920
DISPATCH_OPCODE;
921
922
OPCODE(OPCODE_TYPE_TEST_NATIVE) {
923
CHECK_SPACE(4);
924
925
GET_VARIANT_PTR(dst, 0);
926
GET_VARIANT_PTR(value, 1);
927
928
int native_type_idx = _code_ptr[ip + 3];
929
GD_ERR_BREAK(native_type_idx < 0 || native_type_idx >= _global_names_count);
930
const StringName native_type = _global_names_ptr[native_type_idx];
931
932
bool was_freed = false;
933
Object *object = value->get_validated_object_with_check(was_freed);
934
if (was_freed) {
935
err_text = "Left operand of 'is' is a previously freed instance.";
936
OPCODE_BREAK;
937
}
938
939
*dst = object && ClassDB::is_parent_class(object->get_class_name(), native_type);
940
ip += 4;
941
}
942
DISPATCH_OPCODE;
943
944
OPCODE(OPCODE_TYPE_TEST_SCRIPT) {
945
CHECK_SPACE(4);
946
947
GET_VARIANT_PTR(dst, 0);
948
GET_VARIANT_PTR(value, 1);
949
950
GET_VARIANT_PTR(type, 2);
951
Script *script_type = Object::cast_to<Script>(type->operator Object *());
952
GD_ERR_BREAK(!script_type);
953
954
bool was_freed = false;
955
Object *object = value->get_validated_object_with_check(was_freed);
956
if (was_freed) {
957
err_text = "Left operand of 'is' is a previously freed instance.";
958
OPCODE_BREAK;
959
}
960
961
bool result = false;
962
if (object && object->get_script_instance()) {
963
Script *script_ptr = object->get_script_instance()->get_script().ptr();
964
while (script_ptr) {
965
if (script_ptr == script_type) {
966
result = true;
967
break;
968
}
969
script_ptr = script_ptr->get_base_script().ptr();
970
}
971
}
972
973
*dst = result;
974
ip += 4;
975
}
976
DISPATCH_OPCODE;
977
978
OPCODE(OPCODE_SET_KEYED) {
979
CHECK_SPACE(3);
980
981
GET_VARIANT_PTR(dst, 0);
982
GET_VARIANT_PTR(index, 1);
983
GET_VARIANT_PTR(value, 2);
984
985
bool valid;
986
#ifdef DEBUG_ENABLED
987
Variant::VariantSetError err_code;
988
dst->set(*index, *value, &valid, &err_code);
989
#else
990
dst->set(*index, *value, &valid);
991
#endif
992
#ifdef DEBUG_ENABLED
993
if (!valid) {
994
if (dst->is_read_only()) {
995
err_text = "Invalid assignment on read-only value (on base: '" + _get_var_type(dst) + "').";
996
} else {
997
Object *obj = dst->get_validated_object();
998
String v = index->operator String();
999
bool read_only_property = false;
1000
if (obj) {
1001
read_only_property = ClassDB::has_property(obj->get_class_name(), v) && (ClassDB::get_property_setter(obj->get_class_name(), v) == StringName());
1002
}
1003
if (read_only_property) {
1004
err_text = vformat(R"(Cannot set value into property "%s" (on base "%s") because it is read-only.)", v, _get_var_type(dst));
1005
} else {
1006
if (!v.is_empty()) {
1007
v = "'" + v + "'";
1008
} else {
1009
v = "of type '" + _get_var_type(index) + "'";
1010
}
1011
err_text = "Invalid assignment of property or key " + v + " with value of type '" + _get_var_type(value) + "' on a base object of type '" + _get_var_type(dst) + "'.";
1012
if (err_code == Variant::VariantSetError::SET_INDEXED_ERR) {
1013
err_text = "Invalid assignment of index " + v + " (on base: '" + _get_var_type(dst) + "') with value of type '" + _get_var_type(value) + "'.";
1014
}
1015
}
1016
}
1017
OPCODE_BREAK;
1018
}
1019
#endif
1020
ip += 4;
1021
}
1022
DISPATCH_OPCODE;
1023
1024
OPCODE(OPCODE_SET_KEYED_VALIDATED) {
1025
CHECK_SPACE(4);
1026
1027
GET_VARIANT_PTR(dst, 0);
1028
GET_VARIANT_PTR(index, 1);
1029
GET_VARIANT_PTR(value, 2);
1030
1031
int index_setter = _code_ptr[ip + 4];
1032
GD_ERR_BREAK(index_setter < 0 || index_setter >= _keyed_setters_count);
1033
const Variant::ValidatedKeyedSetter setter = _keyed_setters_ptr[index_setter];
1034
1035
bool valid;
1036
setter(dst, index, value, &valid);
1037
1038
#ifdef DEBUG_ENABLED
1039
if (!valid) {
1040
if (dst->is_read_only()) {
1041
err_text = "Invalid assignment on read-only value (on base: '" + _get_var_type(dst) + "').";
1042
} else {
1043
String v = index->operator String();
1044
if (!v.is_empty()) {
1045
v = "'" + v + "'";
1046
} else {
1047
v = "of type '" + _get_var_type(index) + "'";
1048
}
1049
err_text = "Invalid assignment of property or key " + v + " with value of type '" + _get_var_type(value) + "' on a base object of type '" + _get_var_type(dst) + "'.";
1050
}
1051
OPCODE_BREAK;
1052
}
1053
#endif
1054
ip += 5;
1055
}
1056
DISPATCH_OPCODE;
1057
1058
OPCODE(OPCODE_SET_INDEXED_VALIDATED) {
1059
CHECK_SPACE(4);
1060
1061
GET_VARIANT_PTR(dst, 0);
1062
GET_VARIANT_PTR(index, 1);
1063
GET_VARIANT_PTR(value, 2);
1064
1065
int index_setter = _code_ptr[ip + 4];
1066
GD_ERR_BREAK(index_setter < 0 || index_setter >= _indexed_setters_count);
1067
const Variant::ValidatedIndexedSetter setter = _indexed_setters_ptr[index_setter];
1068
1069
int64_t int_index = *VariantInternal::get_int(index);
1070
1071
bool oob;
1072
setter(dst, int_index, value, &oob);
1073
1074
#ifdef DEBUG_ENABLED
1075
if (oob) {
1076
if (dst->is_read_only()) {
1077
err_text = "Invalid assignment on read-only value (on base: '" + _get_var_type(dst) + "').";
1078
} else {
1079
String v = index->operator String();
1080
if (!v.is_empty()) {
1081
v = "'" + v + "'";
1082
} else {
1083
v = "of type '" + _get_var_type(index) + "'";
1084
}
1085
err_text = "Out of bounds set index " + v + " (on base: '" + _get_var_type(dst) + "')";
1086
}
1087
OPCODE_BREAK;
1088
}
1089
#endif
1090
ip += 5;
1091
}
1092
DISPATCH_OPCODE;
1093
1094
OPCODE(OPCODE_GET_KEYED) {
1095
CHECK_SPACE(3);
1096
1097
GET_VARIANT_PTR(src, 0);
1098
GET_VARIANT_PTR(index, 1);
1099
GET_VARIANT_PTR(dst, 2);
1100
1101
bool valid;
1102
#ifdef DEBUG_ENABLED
1103
// Allow better error message in cases where src and dst are the same stack position.
1104
Variant::VariantGetError err_code;
1105
Variant ret = src->get(*index, &valid, &err_code);
1106
#else
1107
*dst = src->get(*index, &valid);
1108
1109
#endif
1110
#ifdef DEBUG_ENABLED
1111
if (!valid) {
1112
String v = index->operator String();
1113
if (!v.is_empty()) {
1114
v = "'" + v + "'";
1115
} else {
1116
v = "of type '" + _get_var_type(index) + "'";
1117
}
1118
err_text = "Invalid access to property or key " + v + " on a base object of type '" + _get_var_type(src) + "'.";
1119
if (err_code == Variant::VariantGetError::GET_INDEXED_ERR) {
1120
err_text = "Invalid access of index " + v + " on a base object of type: '" + _get_var_type(src) + "'.";
1121
}
1122
OPCODE_BREAK;
1123
}
1124
*dst = ret;
1125
#endif
1126
ip += 4;
1127
}
1128
DISPATCH_OPCODE;
1129
1130
OPCODE(OPCODE_GET_KEYED_VALIDATED) {
1131
CHECK_SPACE(4);
1132
1133
GET_VARIANT_PTR(src, 0);
1134
GET_VARIANT_PTR(key, 1);
1135
GET_VARIANT_PTR(dst, 2);
1136
1137
int index_getter = _code_ptr[ip + 4];
1138
GD_ERR_BREAK(index_getter < 0 || index_getter >= _keyed_getters_count);
1139
const Variant::ValidatedKeyedGetter getter = _keyed_getters_ptr[index_getter];
1140
1141
bool valid;
1142
#ifdef DEBUG_ENABLED
1143
// Allow better error message in cases where src and dst are the same stack position.
1144
Variant ret;
1145
getter(src, key, &ret, &valid);
1146
#else
1147
getter(src, key, dst, &valid);
1148
#endif
1149
#ifdef DEBUG_ENABLED
1150
if (!valid) {
1151
String v = key->operator String();
1152
if (!v.is_empty()) {
1153
v = "'" + v + "'";
1154
} else {
1155
v = "of type '" + _get_var_type(key) + "'";
1156
}
1157
err_text = "Invalid access to property or key " + v + " on a base object of type '" + _get_var_type(src) + "'.";
1158
OPCODE_BREAK;
1159
}
1160
*dst = ret;
1161
#endif
1162
ip += 5;
1163
}
1164
DISPATCH_OPCODE;
1165
1166
OPCODE(OPCODE_GET_INDEXED_VALIDATED) {
1167
CHECK_SPACE(4);
1168
1169
GET_VARIANT_PTR(src, 0);
1170
GET_VARIANT_PTR(index, 1);
1171
GET_VARIANT_PTR(dst, 2);
1172
1173
int index_getter = _code_ptr[ip + 4];
1174
GD_ERR_BREAK(index_getter < 0 || index_getter >= _indexed_getters_count);
1175
const Variant::ValidatedIndexedGetter getter = _indexed_getters_ptr[index_getter];
1176
1177
int64_t int_index = *VariantInternal::get_int(index);
1178
1179
bool oob;
1180
getter(src, int_index, dst, &oob);
1181
1182
#ifdef DEBUG_ENABLED
1183
if (oob) {
1184
String v = index->operator String();
1185
if (!v.is_empty()) {
1186
v = "'" + v + "'";
1187
} else {
1188
v = "of type '" + _get_var_type(index) + "'";
1189
}
1190
err_text = "Out of bounds get index " + v + " (on base: '" + _get_var_type(src) + "')";
1191
OPCODE_BREAK;
1192
}
1193
#endif
1194
ip += 5;
1195
}
1196
DISPATCH_OPCODE;
1197
1198
OPCODE(OPCODE_SET_NAMED) {
1199
CHECK_SPACE(3);
1200
1201
GET_VARIANT_PTR(dst, 0);
1202
GET_VARIANT_PTR(value, 1);
1203
1204
int indexname = _code_ptr[ip + 3];
1205
1206
GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
1207
const StringName *index = &_global_names_ptr[indexname];
1208
1209
bool valid;
1210
dst->set_named(*index, *value, valid);
1211
1212
#ifdef DEBUG_ENABLED
1213
if (!valid) {
1214
if (dst->is_read_only()) {
1215
err_text = "Invalid assignment on read-only value (on base: '" + _get_var_type(dst) + "').";
1216
} else {
1217
Object *obj = dst->get_validated_object();
1218
bool read_only_property = false;
1219
if (obj) {
1220
read_only_property = ClassDB::has_property(obj->get_class_name(), *index) && (ClassDB::get_property_setter(obj->get_class_name(), *index) == StringName());
1221
}
1222
if (read_only_property) {
1223
err_text = vformat(R"(Cannot set value into property "%s" (on base "%s") because it is read-only.)", String(*index), _get_var_type(dst));
1224
} else {
1225
err_text = "Invalid assignment of property or key '" + String(*index) + "' with value of type '" + _get_var_type(value) + "' on a base object of type '" + _get_var_type(dst) + "'.";
1226
}
1227
}
1228
OPCODE_BREAK;
1229
}
1230
#endif
1231
ip += 4;
1232
}
1233
DISPATCH_OPCODE;
1234
1235
OPCODE(OPCODE_SET_NAMED_VALIDATED) {
1236
CHECK_SPACE(3);
1237
1238
GET_VARIANT_PTR(dst, 0);
1239
GET_VARIANT_PTR(value, 1);
1240
1241
int index_setter = _code_ptr[ip + 3];
1242
GD_ERR_BREAK(index_setter < 0 || index_setter >= _setters_count);
1243
const Variant::ValidatedSetter setter = _setters_ptr[index_setter];
1244
1245
setter(dst, value);
1246
ip += 4;
1247
}
1248
DISPATCH_OPCODE;
1249
1250
OPCODE(OPCODE_GET_NAMED) {
1251
CHECK_SPACE(4);
1252
1253
GET_VARIANT_PTR(src, 0);
1254
GET_VARIANT_PTR(dst, 1);
1255
1256
int indexname = _code_ptr[ip + 3];
1257
1258
GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
1259
const StringName *index = &_global_names_ptr[indexname];
1260
1261
bool valid;
1262
#ifdef DEBUG_ENABLED
1263
//allow better error message in cases where src and dst are the same stack position
1264
Variant ret = src->get_named(*index, valid);
1265
1266
#else
1267
*dst = src->get_named(*index, valid);
1268
#endif
1269
#ifdef DEBUG_ENABLED
1270
if (!valid) {
1271
err_text = "Invalid access to property or key '" + index->operator String() + "' on a base object of type '" + _get_var_type(src) + "'.";
1272
OPCODE_BREAK;
1273
}
1274
*dst = ret;
1275
#endif
1276
ip += 4;
1277
}
1278
DISPATCH_OPCODE;
1279
1280
OPCODE(OPCODE_GET_NAMED_VALIDATED) {
1281
CHECK_SPACE(3);
1282
1283
GET_VARIANT_PTR(src, 0);
1284
GET_VARIANT_PTR(dst, 1);
1285
1286
int index_getter = _code_ptr[ip + 3];
1287
GD_ERR_BREAK(index_getter < 0 || index_getter >= _getters_count);
1288
const Variant::ValidatedGetter getter = _getters_ptr[index_getter];
1289
1290
getter(src, dst);
1291
ip += 4;
1292
}
1293
DISPATCH_OPCODE;
1294
1295
OPCODE(OPCODE_SET_MEMBER) {
1296
CHECK_SPACE(3);
1297
GET_VARIANT_PTR(src, 0);
1298
int indexname = _code_ptr[ip + 2];
1299
GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
1300
const StringName *index = &_global_names_ptr[indexname];
1301
1302
bool valid;
1303
#ifndef DEBUG_ENABLED
1304
ClassDB::set_property(p_instance->owner, *index, *src, &valid);
1305
#else
1306
bool ok = ClassDB::set_property(p_instance->owner, *index, *src, &valid);
1307
if (!ok) {
1308
err_text = "Internal error setting property: " + String(*index);
1309
OPCODE_BREAK;
1310
} else if (!valid) {
1311
err_text = "Error setting property '" + String(*index) + "' with value of type " + Variant::get_type_name(src->get_type()) + ".";
1312
OPCODE_BREAK;
1313
}
1314
#endif
1315
ip += 3;
1316
}
1317
DISPATCH_OPCODE;
1318
1319
OPCODE(OPCODE_GET_MEMBER) {
1320
CHECK_SPACE(3);
1321
GET_VARIANT_PTR(dst, 0);
1322
int indexname = _code_ptr[ip + 2];
1323
GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
1324
const StringName *index = &_global_names_ptr[indexname];
1325
#ifndef DEBUG_ENABLED
1326
ClassDB::get_property(p_instance->owner, *index, *dst);
1327
#else
1328
bool ok = ClassDB::get_property(p_instance->owner, *index, *dst);
1329
if (!ok) {
1330
err_text = "Internal error getting property: " + String(*index);
1331
OPCODE_BREAK;
1332
}
1333
#endif
1334
ip += 3;
1335
}
1336
DISPATCH_OPCODE;
1337
1338
OPCODE(OPCODE_SET_STATIC_VARIABLE) {
1339
CHECK_SPACE(4);
1340
1341
GET_VARIANT_PTR(value, 0);
1342
1343
GET_VARIANT_PTR(_class, 1);
1344
GDScript *gdscript = Object::cast_to<GDScript>(_class->operator Object *());
1345
GD_ERR_BREAK(!gdscript);
1346
1347
int index = _code_ptr[ip + 3];
1348
GD_ERR_BREAK(index < 0 || index >= gdscript->static_variables.size());
1349
1350
gdscript->static_variables.write[index] = *value;
1351
1352
ip += 4;
1353
}
1354
DISPATCH_OPCODE;
1355
1356
OPCODE(OPCODE_GET_STATIC_VARIABLE) {
1357
CHECK_SPACE(4);
1358
1359
GET_VARIANT_PTR(target, 0);
1360
1361
GET_VARIANT_PTR(_class, 1);
1362
GDScript *gdscript = Object::cast_to<GDScript>(_class->operator Object *());
1363
GD_ERR_BREAK(!gdscript);
1364
1365
int index = _code_ptr[ip + 3];
1366
GD_ERR_BREAK(index < 0 || index >= gdscript->static_variables.size());
1367
1368
*target = gdscript->static_variables[index];
1369
1370
ip += 4;
1371
}
1372
DISPATCH_OPCODE;
1373
1374
OPCODE(OPCODE_ASSIGN) {
1375
CHECK_SPACE(3);
1376
GET_VARIANT_PTR(dst, 0);
1377
GET_VARIANT_PTR(src, 1);
1378
1379
*dst = *src;
1380
1381
ip += 3;
1382
}
1383
DISPATCH_OPCODE;
1384
1385
OPCODE(OPCODE_ASSIGN_NULL) {
1386
CHECK_SPACE(2);
1387
GET_VARIANT_PTR(dst, 0);
1388
1389
*dst = Variant();
1390
1391
ip += 2;
1392
}
1393
DISPATCH_OPCODE;
1394
1395
OPCODE(OPCODE_ASSIGN_TRUE) {
1396
CHECK_SPACE(2);
1397
GET_VARIANT_PTR(dst, 0);
1398
1399
*dst = true;
1400
1401
ip += 2;
1402
}
1403
DISPATCH_OPCODE;
1404
1405
OPCODE(OPCODE_ASSIGN_FALSE) {
1406
CHECK_SPACE(2);
1407
GET_VARIANT_PTR(dst, 0);
1408
1409
*dst = false;
1410
1411
ip += 2;
1412
}
1413
DISPATCH_OPCODE;
1414
1415
OPCODE(OPCODE_ASSIGN_TYPED_BUILTIN) {
1416
CHECK_SPACE(4);
1417
GET_VARIANT_PTR(dst, 0);
1418
GET_VARIANT_PTR(src, 1);
1419
1420
Variant::Type var_type = (Variant::Type)_code_ptr[ip + 3];
1421
GD_ERR_BREAK(var_type < 0 || var_type >= Variant::VARIANT_MAX);
1422
1423
if (src->get_type() != var_type) {
1424
#ifdef DEBUG_ENABLED
1425
if (Variant::can_convert_strict(src->get_type(), var_type)) {
1426
#endif // DEBUG_ENABLED
1427
Callable::CallError ce;
1428
Variant::construct(var_type, *dst, const_cast<const Variant **>(&src), 1, ce);
1429
} else {
1430
#ifdef DEBUG_ENABLED
1431
err_text = "Trying to assign value of type '" + Variant::get_type_name(src->get_type()) +
1432
"' to a variable of type '" + Variant::get_type_name(var_type) + "'.";
1433
OPCODE_BREAK;
1434
}
1435
} else {
1436
#endif // DEBUG_ENABLED
1437
*dst = *src;
1438
}
1439
1440
ip += 4;
1441
}
1442
DISPATCH_OPCODE;
1443
1444
OPCODE(OPCODE_ASSIGN_TYPED_ARRAY) {
1445
CHECK_SPACE(6);
1446
GET_VARIANT_PTR(dst, 0);
1447
GET_VARIANT_PTR(src, 1);
1448
1449
GET_VARIANT_PTR(script_type, 2);
1450
Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + 4];
1451
int native_type_idx = _code_ptr[ip + 5];
1452
GD_ERR_BREAK(native_type_idx < 0 || native_type_idx >= _global_names_count);
1453
const StringName native_type = _global_names_ptr[native_type_idx];
1454
1455
if (src->get_type() != Variant::ARRAY) {
1456
#ifdef DEBUG_ENABLED
1457
err_text = vformat(R"(Trying to assign a value of type "%s" to a variable of type "Array[%s]".)",
1458
_get_var_type(src), _get_element_type(builtin_type, native_type, *script_type));
1459
#endif // DEBUG_ENABLED
1460
OPCODE_BREAK;
1461
}
1462
1463
Array *array = VariantInternal::get_array(src);
1464
1465
if (array->get_typed_builtin() != ((uint32_t)builtin_type) || array->get_typed_class_name() != native_type || array->get_typed_script() != *script_type) {
1466
#ifdef DEBUG_ENABLED
1467
err_text = vformat(R"(Trying to assign an array of type "%s" to a variable of type "Array[%s]".)",
1468
_get_var_type(src), _get_element_type(builtin_type, native_type, *script_type));
1469
#endif // DEBUG_ENABLED
1470
OPCODE_BREAK;
1471
}
1472
1473
*dst = *src;
1474
1475
ip += 6;
1476
}
1477
DISPATCH_OPCODE;
1478
1479
OPCODE(OPCODE_ASSIGN_TYPED_DICTIONARY) {
1480
CHECK_SPACE(9);
1481
GET_VARIANT_PTR(dst, 0);
1482
GET_VARIANT_PTR(src, 1);
1483
1484
GET_VARIANT_PTR(key_script_type, 2);
1485
Variant::Type key_builtin_type = (Variant::Type)_code_ptr[ip + 5];
1486
int key_native_type_idx = _code_ptr[ip + 6];
1487
GD_ERR_BREAK(key_native_type_idx < 0 || key_native_type_idx >= _global_names_count);
1488
const StringName key_native_type = _global_names_ptr[key_native_type_idx];
1489
1490
GET_VARIANT_PTR(value_script_type, 3);
1491
Variant::Type value_builtin_type = (Variant::Type)_code_ptr[ip + 7];
1492
int value_native_type_idx = _code_ptr[ip + 8];
1493
GD_ERR_BREAK(value_native_type_idx < 0 || value_native_type_idx >= _global_names_count);
1494
const StringName value_native_type = _global_names_ptr[value_native_type_idx];
1495
1496
if (src->get_type() != Variant::DICTIONARY) {
1497
#ifdef DEBUG_ENABLED
1498
err_text = vformat(R"(Trying to assign a value of type "%s" to a variable of type "Dictionary[%s, %s]".)",
1499
_get_var_type(src), _get_element_type(key_builtin_type, key_native_type, *key_script_type),
1500
_get_element_type(value_builtin_type, value_native_type, *value_script_type));
1501
#endif // DEBUG_ENABLED
1502
OPCODE_BREAK;
1503
}
1504
1505
Dictionary *dictionary = VariantInternal::get_dictionary(src);
1506
1507
if (dictionary->get_typed_key_builtin() != ((uint32_t)key_builtin_type) || dictionary->get_typed_key_class_name() != key_native_type || dictionary->get_typed_key_script() != *key_script_type ||
1508
dictionary->get_typed_value_builtin() != ((uint32_t)value_builtin_type) || dictionary->get_typed_value_class_name() != value_native_type || dictionary->get_typed_value_script() != *value_script_type) {
1509
#ifdef DEBUG_ENABLED
1510
err_text = vformat(R"(Trying to assign a dictionary of type "%s" to a variable of type "Dictionary[%s, %s]".)",
1511
_get_var_type(src), _get_element_type(key_builtin_type, key_native_type, *key_script_type),
1512
_get_element_type(value_builtin_type, value_native_type, *value_script_type));
1513
#endif // DEBUG_ENABLED
1514
OPCODE_BREAK;
1515
}
1516
1517
*dst = *src;
1518
1519
ip += 9;
1520
}
1521
DISPATCH_OPCODE;
1522
1523
OPCODE(OPCODE_ASSIGN_TYPED_NATIVE) {
1524
CHECK_SPACE(4);
1525
GET_VARIANT_PTR(dst, 0);
1526
GET_VARIANT_PTR(src, 1);
1527
1528
#ifdef DEBUG_ENABLED
1529
GET_VARIANT_PTR(type, 2);
1530
GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(type->operator Object *());
1531
GD_ERR_BREAK(!nc);
1532
if (src->get_type() != Variant::OBJECT && src->get_type() != Variant::NIL) {
1533
err_text = "Trying to assign value of type '" + Variant::get_type_name(src->get_type()) +
1534
"' to a variable of type '" + nc->get_name() + "'.";
1535
OPCODE_BREAK;
1536
}
1537
1538
if (src->get_type() == Variant::OBJECT) {
1539
bool was_freed = false;
1540
Object *src_obj = src->get_validated_object_with_check(was_freed);
1541
if (!src_obj && was_freed) {
1542
err_text = "Trying to assign invalid previously freed instance.";
1543
OPCODE_BREAK;
1544
}
1545
1546
if (src_obj && !ClassDB::is_parent_class(src_obj->get_class_name(), nc->get_name())) {
1547
err_text = "Trying to assign value of type '" + src_obj->get_class_name() +
1548
"' to a variable of type '" + nc->get_name() + "'.";
1549
OPCODE_BREAK;
1550
}
1551
}
1552
#endif // DEBUG_ENABLED
1553
*dst = *src;
1554
1555
ip += 4;
1556
}
1557
DISPATCH_OPCODE;
1558
1559
OPCODE(OPCODE_ASSIGN_TYPED_SCRIPT) {
1560
CHECK_SPACE(4);
1561
GET_VARIANT_PTR(dst, 0);
1562
GET_VARIANT_PTR(src, 1);
1563
1564
#ifdef DEBUG_ENABLED
1565
GET_VARIANT_PTR(type, 2);
1566
Script *base_type = Object::cast_to<Script>(type->operator Object *());
1567
1568
GD_ERR_BREAK(!base_type);
1569
1570
if (src->get_type() != Variant::OBJECT && src->get_type() != Variant::NIL) {
1571
err_text = "Trying to assign a non-object value to a variable of type '" + base_type->get_path().get_file() + "'.";
1572
OPCODE_BREAK;
1573
}
1574
1575
if (src->get_type() == Variant::OBJECT) {
1576
bool was_freed = false;
1577
Object *val_obj = src->get_validated_object_with_check(was_freed);
1578
if (!val_obj && was_freed) {
1579
err_text = "Trying to assign invalid previously freed instance.";
1580
OPCODE_BREAK;
1581
}
1582
1583
if (val_obj) { // src is not null
1584
ScriptInstance *scr_inst = val_obj->get_script_instance();
1585
if (!scr_inst) {
1586
err_text = "Trying to assign value of type '" + val_obj->get_class_name() +
1587
"' to a variable of type '" + base_type->get_path().get_file() + "'.";
1588
OPCODE_BREAK;
1589
}
1590
1591
Script *src_type = scr_inst->get_script().ptr();
1592
bool valid = false;
1593
1594
while (src_type) {
1595
if (src_type == base_type) {
1596
valid = true;
1597
break;
1598
}
1599
src_type = src_type->get_base_script().ptr();
1600
}
1601
1602
if (!valid) {
1603
err_text = "Trying to assign value of type '" + val_obj->get_script_instance()->get_script()->get_path().get_file() +
1604
"' to a variable of type '" + base_type->get_path().get_file() + "'.";
1605
OPCODE_BREAK;
1606
}
1607
}
1608
}
1609
#endif // DEBUG_ENABLED
1610
1611
*dst = *src;
1612
1613
ip += 4;
1614
}
1615
DISPATCH_OPCODE;
1616
1617
OPCODE(OPCODE_CAST_TO_BUILTIN) {
1618
CHECK_SPACE(4);
1619
GET_VARIANT_PTR(src, 0);
1620
GET_VARIANT_PTR(dst, 1);
1621
Variant::Type to_type = (Variant::Type)_code_ptr[ip + 3];
1622
1623
GD_ERR_BREAK(to_type < 0 || to_type >= Variant::VARIANT_MAX);
1624
1625
#ifdef DEBUG_ENABLED
1626
if (src->operator Object *() && !src->get_validated_object()) {
1627
err_text = "Trying to cast a freed object.";
1628
OPCODE_BREAK;
1629
}
1630
#endif
1631
1632
Callable::CallError err;
1633
Variant::construct(to_type, *dst, (const Variant **)&src, 1, err);
1634
1635
#ifdef DEBUG_ENABLED
1636
if (err.error != Callable::CallError::CALL_OK) {
1637
err_text = "Invalid cast: could not convert value to '" + Variant::get_type_name(to_type) + "'.";
1638
OPCODE_BREAK;
1639
}
1640
#endif
1641
1642
ip += 4;
1643
}
1644
DISPATCH_OPCODE;
1645
1646
OPCODE(OPCODE_CAST_TO_NATIVE) {
1647
CHECK_SPACE(4);
1648
GET_VARIANT_PTR(src, 0);
1649
GET_VARIANT_PTR(dst, 1);
1650
GET_VARIANT_PTR(to_type, 2);
1651
1652
GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(to_type->operator Object *());
1653
GD_ERR_BREAK(!nc);
1654
1655
#ifdef DEBUG_ENABLED
1656
if (src->operator Object *() && !src->get_validated_object()) {
1657
err_text = "Trying to cast a freed object.";
1658
OPCODE_BREAK;
1659
}
1660
if (src->get_type() != Variant::OBJECT && src->get_type() != Variant::NIL) {
1661
err_text = "Invalid cast: can't convert a non-object value to an object type.";
1662
OPCODE_BREAK;
1663
}
1664
#endif
1665
Object *src_obj = src->operator Object *();
1666
1667
if (src_obj && !ClassDB::is_parent_class(src_obj->get_class_name(), nc->get_name())) {
1668
*dst = Variant(); // invalid cast, assign NULL
1669
} else {
1670
*dst = *src;
1671
}
1672
1673
ip += 4;
1674
}
1675
DISPATCH_OPCODE;
1676
1677
OPCODE(OPCODE_CAST_TO_SCRIPT) {
1678
CHECK_SPACE(4);
1679
GET_VARIANT_PTR(src, 0);
1680
GET_VARIANT_PTR(dst, 1);
1681
GET_VARIANT_PTR(to_type, 2);
1682
1683
Script *base_type = Object::cast_to<Script>(to_type->operator Object *());
1684
1685
GD_ERR_BREAK(!base_type);
1686
1687
#ifdef DEBUG_ENABLED
1688
if (src->operator Object *() && !src->get_validated_object()) {
1689
err_text = "Trying to cast a freed object.";
1690
OPCODE_BREAK;
1691
}
1692
if (src->get_type() != Variant::OBJECT && src->get_type() != Variant::NIL) {
1693
err_text = "Trying to assign a non-object value to a variable of type '" + base_type->get_path().get_file() + "'.";
1694
OPCODE_BREAK;
1695
}
1696
#endif
1697
1698
bool valid = false;
1699
1700
if (src->get_type() != Variant::NIL && src->operator Object *() != nullptr) {
1701
ScriptInstance *scr_inst = src->operator Object *()->get_script_instance();
1702
1703
if (scr_inst) {
1704
Script *src_type = src->operator Object *()->get_script_instance()->get_script().ptr();
1705
1706
while (src_type) {
1707
if (src_type == base_type) {
1708
valid = true;
1709
break;
1710
}
1711
src_type = src_type->get_base_script().ptr();
1712
}
1713
}
1714
}
1715
1716
if (valid) {
1717
*dst = *src; // Valid cast, copy the source object
1718
} else {
1719
*dst = Variant(); // invalid cast, assign NULL
1720
}
1721
1722
ip += 4;
1723
}
1724
DISPATCH_OPCODE;
1725
1726
OPCODE(OPCODE_CONSTRUCT) {
1727
LOAD_INSTRUCTION_ARGS
1728
CHECK_SPACE(2 + instr_arg_count);
1729
1730
ip += instr_arg_count;
1731
1732
int argc = _code_ptr[ip + 1];
1733
1734
Variant::Type t = Variant::Type(_code_ptr[ip + 2]);
1735
1736
Variant **argptrs = instruction_args;
1737
1738
GET_INSTRUCTION_ARG(dst, argc);
1739
1740
Callable::CallError err;
1741
Variant::construct(t, *dst, (const Variant **)argptrs, argc, err);
1742
1743
#ifdef DEBUG_ENABLED
1744
if (err.error != Callable::CallError::CALL_OK) {
1745
err_text = _get_call_error("'" + Variant::get_type_name(t) + "' constructor", (const Variant **)argptrs, argc, *dst, err);
1746
OPCODE_BREAK;
1747
}
1748
#endif
1749
1750
ip += 3;
1751
}
1752
DISPATCH_OPCODE;
1753
1754
OPCODE(OPCODE_CONSTRUCT_VALIDATED) {
1755
LOAD_INSTRUCTION_ARGS
1756
CHECK_SPACE(2 + instr_arg_count);
1757
ip += instr_arg_count;
1758
1759
int argc = _code_ptr[ip + 1];
1760
1761
int constructor_idx = _code_ptr[ip + 2];
1762
GD_ERR_BREAK(constructor_idx < 0 || constructor_idx >= _constructors_count);
1763
Variant::ValidatedConstructor constructor = _constructors_ptr[constructor_idx];
1764
1765
Variant **argptrs = instruction_args;
1766
1767
GET_INSTRUCTION_ARG(dst, argc);
1768
1769
constructor(dst, (const Variant **)argptrs);
1770
1771
ip += 3;
1772
}
1773
DISPATCH_OPCODE;
1774
1775
OPCODE(OPCODE_CONSTRUCT_ARRAY) {
1776
LOAD_INSTRUCTION_ARGS
1777
CHECK_SPACE(1 + instr_arg_count);
1778
ip += instr_arg_count;
1779
1780
int argc = _code_ptr[ip + 1];
1781
Array array;
1782
array.resize(argc);
1783
1784
for (int i = 0; i < argc; i++) {
1785
array[i] = *(instruction_args[i]);
1786
}
1787
1788
GET_INSTRUCTION_ARG(dst, argc);
1789
*dst = Variant(); // Clear potential previous typed array.
1790
1791
*dst = array;
1792
1793
ip += 2;
1794
}
1795
DISPATCH_OPCODE;
1796
1797
OPCODE(OPCODE_CONSTRUCT_TYPED_ARRAY) {
1798
LOAD_INSTRUCTION_ARGS
1799
CHECK_SPACE(3 + instr_arg_count);
1800
ip += instr_arg_count;
1801
1802
int argc = _code_ptr[ip + 1];
1803
1804
GET_INSTRUCTION_ARG(script_type, argc + 1);
1805
Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + 2];
1806
int native_type_idx = _code_ptr[ip + 3];
1807
GD_ERR_BREAK(native_type_idx < 0 || native_type_idx >= _global_names_count);
1808
const StringName native_type = _global_names_ptr[native_type_idx];
1809
1810
Array array;
1811
array.set_typed(builtin_type, native_type, *script_type);
1812
array.resize(argc);
1813
for (int i = 0; i < argc; i++) {
1814
// Use .set instead of operator[] to handle type conversion / validation.
1815
array.set(i, *(instruction_args[i]));
1816
}
1817
1818
GET_INSTRUCTION_ARG(dst, argc);
1819
*dst = Variant(); // Clear potential previous typed array.
1820
1821
*dst = array;
1822
1823
ip += 4;
1824
}
1825
DISPATCH_OPCODE;
1826
1827
OPCODE(OPCODE_CONSTRUCT_DICTIONARY) {
1828
LOAD_INSTRUCTION_ARGS
1829
CHECK_SPACE(2 + instr_arg_count);
1830
1831
ip += instr_arg_count;
1832
1833
int argc = _code_ptr[ip + 1];
1834
Dictionary dict;
1835
dict.reserve(argc);
1836
for (int i = 0; i < argc; i++) {
1837
GET_INSTRUCTION_ARG(k, i * 2 + 0);
1838
GET_INSTRUCTION_ARG(v, i * 2 + 1);
1839
dict[*k] = *v;
1840
}
1841
1842
GET_INSTRUCTION_ARG(dst, argc * 2);
1843
1844
*dst = Variant(); // Clear potential previous typed dictionary.
1845
1846
*dst = dict;
1847
1848
ip += 2;
1849
}
1850
DISPATCH_OPCODE;
1851
1852
OPCODE(OPCODE_CONSTRUCT_TYPED_DICTIONARY) {
1853
LOAD_INSTRUCTION_ARGS
1854
CHECK_SPACE(6 + instr_arg_count);
1855
ip += instr_arg_count;
1856
1857
int argc = _code_ptr[ip + 1];
1858
1859
GET_INSTRUCTION_ARG(key_script_type, argc * 2 + 1);
1860
Variant::Type key_builtin_type = (Variant::Type)_code_ptr[ip + 2];
1861
int key_native_type_idx = _code_ptr[ip + 3];
1862
GD_ERR_BREAK(key_native_type_idx < 0 || key_native_type_idx >= _global_names_count);
1863
const StringName key_native_type = _global_names_ptr[key_native_type_idx];
1864
1865
GET_INSTRUCTION_ARG(value_script_type, argc * 2 + 2);
1866
Variant::Type value_builtin_type = (Variant::Type)_code_ptr[ip + 4];
1867
int value_native_type_idx = _code_ptr[ip + 5];
1868
GD_ERR_BREAK(value_native_type_idx < 0 || value_native_type_idx >= _global_names_count);
1869
const StringName value_native_type = _global_names_ptr[value_native_type_idx];
1870
1871
Dictionary dict;
1872
dict.set_typed(key_builtin_type, key_native_type, *key_script_type, value_builtin_type, value_native_type, *value_script_type);
1873
dict.reserve(argc);
1874
for (int i = 0; i < argc; i++) {
1875
GET_INSTRUCTION_ARG(k, i * 2 + 0);
1876
GET_INSTRUCTION_ARG(v, i * 2 + 1);
1877
// Use .set instead of operator[] to handle type conversion / validation.
1878
dict.set(*k, *v);
1879
}
1880
1881
GET_INSTRUCTION_ARG(dst, argc * 2);
1882
1883
*dst = Variant(); // Clear potential previous typed dictionary.
1884
1885
*dst = dict;
1886
1887
ip += 6;
1888
}
1889
DISPATCH_OPCODE;
1890
1891
OPCODE(OPCODE_CALL_ASYNC)
1892
OPCODE(OPCODE_CALL_RETURN)
1893
OPCODE(OPCODE_CALL) {
1894
bool call_ret = (_code_ptr[ip]) != OPCODE_CALL;
1895
#ifdef DEBUG_ENABLED
1896
bool call_async = (_code_ptr[ip]) == OPCODE_CALL_ASYNC;
1897
#endif
1898
LOAD_INSTRUCTION_ARGS
1899
CHECK_SPACE(3 + instr_arg_count);
1900
1901
ip += instr_arg_count;
1902
1903
int argc = _code_ptr[ip + 1];
1904
GD_ERR_BREAK(argc < 0);
1905
1906
int methodname_idx = _code_ptr[ip + 2];
1907
GD_ERR_BREAK(methodname_idx < 0 || methodname_idx >= _global_names_count);
1908
const StringName *methodname = &_global_names_ptr[methodname_idx];
1909
1910
GodotProfileZoneScriptSystemCall(methodname, source, name, *methodname, line);
1911
1912
GET_INSTRUCTION_ARG(base, argc);
1913
Variant **argptrs = instruction_args;
1914
1915
#ifdef DEBUG_ENABLED
1916
uint64_t call_time = 0;
1917
1918
if (GDScriptLanguage::get_singleton()->profiling) {
1919
call_time = OS::get_singleton()->get_ticks_usec();
1920
}
1921
Variant::Type base_type = base->get_type();
1922
Object *base_obj = base->get_validated_object();
1923
StringName base_class = base_obj ? base_obj->get_class_name() : StringName();
1924
#endif
1925
1926
Variant temp_ret;
1927
Callable::CallError err;
1928
if (call_ret) {
1929
GET_INSTRUCTION_ARG(ret, argc + 1);
1930
base->callp(*methodname, (const Variant **)argptrs, argc, temp_ret, err);
1931
*ret = temp_ret;
1932
#ifdef DEBUG_ENABLED
1933
if (ret->get_type() == Variant::NIL) {
1934
if (base_type == Variant::OBJECT) {
1935
if (base_obj) {
1936
MethodBind *method = ClassDB::get_method(base_class, *methodname);
1937
if (*methodname == CoreStringName(free_) || (method && !method->has_return())) {
1938
err_text = R"(Trying to get a return value of a method that returns "void")";
1939
OPCODE_BREAK;
1940
}
1941
}
1942
} else if (Variant::has_builtin_method(base_type, *methodname) && !Variant::has_builtin_method_return_value(base_type, *methodname)) {
1943
err_text = R"(Trying to get a return value of a method that returns "void")";
1944
OPCODE_BREAK;
1945
}
1946
}
1947
1948
if (!call_async && ret->get_type() == Variant::OBJECT) {
1949
// Check if getting a function state without await.
1950
bool was_freed = false;
1951
Object *obj = ret->get_validated_object_with_check(was_freed);
1952
1953
if (obj && obj->is_class_ptr(GDScriptFunctionState::get_class_ptr_static())) {
1954
err_text = R"(Trying to call an async function without "await".)";
1955
OPCODE_BREAK;
1956
}
1957
}
1958
#endif
1959
} else {
1960
base->callp(*methodname, (const Variant **)argptrs, argc, temp_ret, err);
1961
}
1962
#ifdef DEBUG_ENABLED
1963
1964
if (GDScriptLanguage::get_singleton()->profiling) {
1965
uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
1966
if (GDScriptLanguage::get_singleton()->profile_native_calls && _profile_count_as_native(base_obj, *methodname)) {
1967
_profile_native_call(t_taken, *methodname, base_class);
1968
}
1969
function_call_time += t_taken;
1970
}
1971
1972
if (err.error != Callable::CallError::CALL_OK) {
1973
String methodstr = *methodname;
1974
String basestr = _get_var_type(base);
1975
bool is_callable = false;
1976
1977
if (methodstr == "call") {
1978
if (argc >= 1 && base->get_type() != Variant::CALLABLE) {
1979
methodstr = String(*argptrs[0]) + " (via call)";
1980
if (err.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) {
1981
err.argument += 1;
1982
}
1983
} else {
1984
methodstr = base->operator String() + " (Callable)";
1985
is_callable = true;
1986
}
1987
} else if (methodstr == "free") {
1988
if (err.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) {
1989
if (base->is_ref_counted()) {
1990
err_text = "Attempted to free a RefCounted object.";
1991
OPCODE_BREAK;
1992
} else if (base->get_type() == Variant::OBJECT) {
1993
err_text = "Attempted to free a locked object (calling or emitting).";
1994
OPCODE_BREAK;
1995
}
1996
}
1997
} else if (methodstr == "call_recursive" && basestr == "TreeItem") {
1998
if (argc >= 1) {
1999
methodstr = String(*argptrs[0]) + " (via TreeItem.call_recursive)";
2000
if (err.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) {
2001
err.argument += 1;
2002
}
2003
}
2004
}
2005
2006
if (is_callable) {
2007
err_text = _get_callable_call_error(vformat("function '%s'", methodstr), *base, (const Variant **)argptrs, argc, temp_ret, err);
2008
} else {
2009
err_text = _get_call_error(vformat("function '%s' in base '%s'", methodstr, basestr), (const Variant **)argptrs, argc, temp_ret, err);
2010
}
2011
OPCODE_BREAK;
2012
}
2013
#endif // DEBUG_ENABLED
2014
2015
ip += 3;
2016
}
2017
DISPATCH_OPCODE;
2018
2019
OPCODE(OPCODE_CALL_METHOD_BIND)
2020
OPCODE(OPCODE_CALL_METHOD_BIND_RET) {
2021
bool call_ret = (_code_ptr[ip]) == OPCODE_CALL_METHOD_BIND_RET;
2022
LOAD_INSTRUCTION_ARGS
2023
CHECK_SPACE(3 + instr_arg_count);
2024
2025
ip += instr_arg_count;
2026
2027
int argc = _code_ptr[ip + 1];
2028
GD_ERR_BREAK(argc < 0);
2029
GD_ERR_BREAK(_code_ptr[ip + 2] < 0 || _code_ptr[ip + 2] >= _methods_count);
2030
MethodBind *method = _methods_ptr[_code_ptr[ip + 2]];
2031
2032
GodotProfileZoneScriptSystemCall(method, source, name, method->get_name(), line);
2033
2034
GET_INSTRUCTION_ARG(base, argc);
2035
2036
#ifdef DEBUG_ENABLED
2037
bool freed = false;
2038
Object *base_obj = base->get_validated_object_with_check(freed);
2039
if (freed) {
2040
err_text = METHOD_CALL_ON_FREED_INSTANCE_ERROR(method);
2041
OPCODE_BREAK;
2042
} else if (!base_obj) {
2043
err_text = METHOD_CALL_ON_NULL_VALUE_ERROR(method);
2044
OPCODE_BREAK;
2045
}
2046
#else
2047
Object *base_obj = base->operator Object *();
2048
#endif
2049
Variant **argptrs = instruction_args;
2050
2051
#ifdef DEBUG_ENABLED
2052
uint64_t call_time = 0;
2053
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2054
call_time = OS::get_singleton()->get_ticks_usec();
2055
}
2056
#endif
2057
2058
Variant temp_ret;
2059
Callable::CallError err;
2060
if (call_ret) {
2061
GET_INSTRUCTION_ARG(ret, argc + 1);
2062
temp_ret = method->call(base_obj, (const Variant **)argptrs, argc, err);
2063
*ret = temp_ret;
2064
} else {
2065
temp_ret = method->call(base_obj, (const Variant **)argptrs, argc, err);
2066
}
2067
2068
#ifdef DEBUG_ENABLED
2069
2070
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2071
uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
2072
_profile_native_call(t_taken, method->get_name(), method->get_instance_class());
2073
function_call_time += t_taken;
2074
}
2075
2076
if (err.error != Callable::CallError::CALL_OK) {
2077
String methodstr = method->get_name();
2078
String basestr = _get_var_type(base);
2079
2080
if (methodstr == "call") {
2081
if (argc >= 1) {
2082
methodstr = String(*argptrs[0]) + " (via call)";
2083
if (err.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) {
2084
err.argument += 1;
2085
}
2086
}
2087
} else if (methodstr == "free") {
2088
if (err.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) {
2089
if (base->is_ref_counted()) {
2090
err_text = "Attempted to free a RefCounted object.";
2091
OPCODE_BREAK;
2092
} else if (base->get_type() == Variant::OBJECT) {
2093
err_text = "Attempted to free a locked object (calling or emitting).";
2094
OPCODE_BREAK;
2095
}
2096
}
2097
}
2098
err_text = _get_call_error("function '" + methodstr + "' in base '" + basestr + "'", (const Variant **)argptrs, argc, temp_ret, err);
2099
OPCODE_BREAK;
2100
}
2101
#endif
2102
ip += 3;
2103
}
2104
DISPATCH_OPCODE;
2105
2106
OPCODE(OPCODE_CALL_BUILTIN_STATIC) {
2107
LOAD_INSTRUCTION_ARGS
2108
CHECK_SPACE(4 + instr_arg_count);
2109
2110
ip += instr_arg_count;
2111
2112
GD_ERR_BREAK(_code_ptr[ip + 1] < 0 || _code_ptr[ip + 1] >= Variant::VARIANT_MAX);
2113
Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + 1];
2114
2115
int methodname_idx = _code_ptr[ip + 2];
2116
GD_ERR_BREAK(methodname_idx < 0 || methodname_idx >= _global_names_count);
2117
const StringName *methodname = &_global_names_ptr[methodname_idx];
2118
2119
GodotProfileZoneScriptSystemCall(methodname, source, name, *methodname, line);
2120
2121
int argc = _code_ptr[ip + 3];
2122
GD_ERR_BREAK(argc < 0);
2123
2124
GET_INSTRUCTION_ARG(ret, argc);
2125
2126
const Variant **argptrs = const_cast<const Variant **>(instruction_args);
2127
2128
Callable::CallError err;
2129
Variant::call_static(builtin_type, *methodname, argptrs, argc, *ret, err);
2130
2131
#ifdef DEBUG_ENABLED
2132
if (err.error != Callable::CallError::CALL_OK) {
2133
err_text = _get_call_error("static function '" + methodname->operator String() + "' in type '" + Variant::get_type_name(builtin_type) + "'", argptrs, argc, *ret, err);
2134
OPCODE_BREAK;
2135
}
2136
#endif
2137
2138
ip += 4;
2139
}
2140
DISPATCH_OPCODE;
2141
2142
OPCODE(OPCODE_CALL_NATIVE_STATIC) {
2143
LOAD_INSTRUCTION_ARGS
2144
CHECK_SPACE(3 + instr_arg_count);
2145
2146
ip += instr_arg_count;
2147
2148
GD_ERR_BREAK(_code_ptr[ip + 1] < 0 || _code_ptr[ip + 1] >= _methods_count);
2149
MethodBind *method = _methods_ptr[_code_ptr[ip + 1]];
2150
2151
GodotProfileZoneScriptSystemCall(method, source, name, method->get_name(), line);
2152
2153
int argc = _code_ptr[ip + 2];
2154
GD_ERR_BREAK(argc < 0);
2155
2156
GET_INSTRUCTION_ARG(ret, argc);
2157
2158
const Variant **argptrs = const_cast<const Variant **>(instruction_args);
2159
2160
#ifdef DEBUG_ENABLED
2161
uint64_t call_time = 0;
2162
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2163
call_time = OS::get_singleton()->get_ticks_usec();
2164
}
2165
#endif
2166
2167
Callable::CallError err;
2168
*ret = method->call(nullptr, argptrs, argc, err);
2169
2170
#ifdef DEBUG_ENABLED
2171
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2172
uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
2173
_profile_native_call(t_taken, method->get_name(), method->get_instance_class());
2174
function_call_time += t_taken;
2175
}
2176
#endif
2177
2178
if (err.error != Callable::CallError::CALL_OK) {
2179
err_text = _get_call_error("static function '" + method->get_name().operator String() + "' in type '" + method->get_instance_class().operator String() + "'", argptrs, argc, *ret, err);
2180
OPCODE_BREAK;
2181
}
2182
2183
ip += 3;
2184
}
2185
DISPATCH_OPCODE;
2186
2187
OPCODE(OPCODE_CALL_NATIVE_STATIC_VALIDATED_RETURN) {
2188
LOAD_INSTRUCTION_ARGS
2189
CHECK_SPACE(3 + instr_arg_count);
2190
2191
ip += instr_arg_count;
2192
2193
int argc = _code_ptr[ip + 1];
2194
GD_ERR_BREAK(argc < 0);
2195
2196
GD_ERR_BREAK(_code_ptr[ip + 2] < 0 || _code_ptr[ip + 2] >= _methods_count);
2197
MethodBind *method = _methods_ptr[_code_ptr[ip + 2]];
2198
2199
GodotProfileZoneScriptSystemCall(method, source, name, method->get_name(), line);
2200
2201
Variant **argptrs = instruction_args;
2202
2203
#ifdef DEBUG_ENABLED
2204
uint64_t call_time = 0;
2205
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2206
call_time = OS::get_singleton()->get_ticks_usec();
2207
}
2208
#endif
2209
2210
GET_INSTRUCTION_ARG(ret, argc);
2211
method->validated_call(nullptr, (const Variant **)argptrs, ret);
2212
2213
#ifdef DEBUG_ENABLED
2214
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2215
uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
2216
_profile_native_call(t_taken, method->get_name(), method->get_instance_class());
2217
function_call_time += t_taken;
2218
}
2219
#endif
2220
2221
ip += 3;
2222
}
2223
DISPATCH_OPCODE;
2224
2225
OPCODE(OPCODE_CALL_NATIVE_STATIC_VALIDATED_NO_RETURN) {
2226
LOAD_INSTRUCTION_ARGS
2227
CHECK_SPACE(3 + instr_arg_count);
2228
2229
ip += instr_arg_count;
2230
2231
int argc = _code_ptr[ip + 1];
2232
GD_ERR_BREAK(argc < 0);
2233
2234
GD_ERR_BREAK(_code_ptr[ip + 2] < 0 || _code_ptr[ip + 2] >= _methods_count);
2235
MethodBind *method = _methods_ptr[_code_ptr[ip + 2]];
2236
2237
GodotProfileZoneScriptSystemCall(method, source, name, method->get_name(), line);
2238
2239
Variant **argptrs = instruction_args;
2240
#ifdef DEBUG_ENABLED
2241
uint64_t call_time = 0;
2242
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2243
call_time = OS::get_singleton()->get_ticks_usec();
2244
}
2245
#endif
2246
2247
GET_INSTRUCTION_ARG(ret, argc);
2248
VariantInternal::initialize(ret, Variant::NIL);
2249
method->validated_call(nullptr, (const Variant **)argptrs, nullptr);
2250
2251
#ifdef DEBUG_ENABLED
2252
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2253
uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
2254
_profile_native_call(t_taken, method->get_name(), method->get_instance_class());
2255
function_call_time += t_taken;
2256
}
2257
#endif
2258
2259
ip += 3;
2260
}
2261
DISPATCH_OPCODE;
2262
2263
OPCODE(OPCODE_CALL_METHOD_BIND_VALIDATED_RETURN) {
2264
LOAD_INSTRUCTION_ARGS
2265
CHECK_SPACE(3 + instr_arg_count);
2266
2267
ip += instr_arg_count;
2268
2269
int argc = _code_ptr[ip + 1];
2270
GD_ERR_BREAK(argc < 0);
2271
2272
GD_ERR_BREAK(_code_ptr[ip + 2] < 0 || _code_ptr[ip + 2] >= _methods_count);
2273
MethodBind *method = _methods_ptr[_code_ptr[ip + 2]];
2274
2275
GodotProfileZoneScriptSystemCall(method, source, name, method->get_name(), line);
2276
2277
GET_INSTRUCTION_ARG(base, argc);
2278
2279
#ifdef DEBUG_ENABLED
2280
bool freed = false;
2281
Object *base_obj = base->get_validated_object_with_check(freed);
2282
if (freed) {
2283
err_text = METHOD_CALL_ON_FREED_INSTANCE_ERROR(method);
2284
OPCODE_BREAK;
2285
} else if (!base_obj) {
2286
err_text = METHOD_CALL_ON_NULL_VALUE_ERROR(method);
2287
OPCODE_BREAK;
2288
}
2289
#else
2290
Object *base_obj = *VariantInternal::get_object(base);
2291
#endif
2292
2293
Variant **argptrs = instruction_args;
2294
2295
#ifdef DEBUG_ENABLED
2296
uint64_t call_time = 0;
2297
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2298
call_time = OS::get_singleton()->get_ticks_usec();
2299
}
2300
#endif
2301
2302
GET_INSTRUCTION_ARG(ret, argc + 1);
2303
method->validated_call(base_obj, (const Variant **)argptrs, ret);
2304
2305
#ifdef DEBUG_ENABLED
2306
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2307
uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
2308
_profile_native_call(t_taken, method->get_name(), method->get_instance_class());
2309
function_call_time += t_taken;
2310
}
2311
#endif
2312
2313
ip += 3;
2314
}
2315
DISPATCH_OPCODE;
2316
2317
OPCODE(OPCODE_CALL_METHOD_BIND_VALIDATED_NO_RETURN) {
2318
LOAD_INSTRUCTION_ARGS
2319
CHECK_SPACE(3 + instr_arg_count);
2320
2321
ip += instr_arg_count;
2322
2323
int argc = _code_ptr[ip + 1];
2324
GD_ERR_BREAK(argc < 0);
2325
2326
GD_ERR_BREAK(_code_ptr[ip + 2] < 0 || _code_ptr[ip + 2] >= _methods_count);
2327
MethodBind *method = _methods_ptr[_code_ptr[ip + 2]];
2328
2329
GodotProfileZoneScriptSystemCall(method, source, name, method->get_name(), line);
2330
2331
GET_INSTRUCTION_ARG(base, argc);
2332
#ifdef DEBUG_ENABLED
2333
bool freed = false;
2334
Object *base_obj = base->get_validated_object_with_check(freed);
2335
if (freed) {
2336
err_text = METHOD_CALL_ON_FREED_INSTANCE_ERROR(method);
2337
OPCODE_BREAK;
2338
} else if (!base_obj) {
2339
err_text = METHOD_CALL_ON_NULL_VALUE_ERROR(method);
2340
OPCODE_BREAK;
2341
}
2342
#else
2343
Object *base_obj = *VariantInternal::get_object(base);
2344
#endif
2345
Variant **argptrs = instruction_args;
2346
#ifdef DEBUG_ENABLED
2347
uint64_t call_time = 0;
2348
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2349
call_time = OS::get_singleton()->get_ticks_usec();
2350
}
2351
#endif
2352
2353
GET_INSTRUCTION_ARG(ret, argc + 1);
2354
VariantInternal::initialize(ret, Variant::NIL);
2355
method->validated_call(base_obj, (const Variant **)argptrs, nullptr);
2356
2357
#ifdef DEBUG_ENABLED
2358
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2359
uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
2360
_profile_native_call(t_taken, method->get_name(), method->get_instance_class());
2361
function_call_time += t_taken;
2362
}
2363
#endif
2364
2365
ip += 3;
2366
}
2367
DISPATCH_OPCODE;
2368
2369
OPCODE(OPCODE_CALL_BUILTIN_TYPE_VALIDATED) {
2370
LOAD_INSTRUCTION_ARGS
2371
2372
CHECK_SPACE(3 + instr_arg_count);
2373
2374
ip += instr_arg_count;
2375
2376
int argc = _code_ptr[ip + 1];
2377
GD_ERR_BREAK(argc < 0);
2378
2379
GET_INSTRUCTION_ARG(base, argc);
2380
2381
GD_ERR_BREAK(_code_ptr[ip + 2] < 0 || _code_ptr[ip + 2] >= _builtin_methods_count);
2382
Variant::ValidatedBuiltInMethod method = _builtin_methods_ptr[_code_ptr[ip + 2]];
2383
Variant **argptrs = instruction_args;
2384
2385
GET_INSTRUCTION_ARG(ret, argc + 1);
2386
method(base, (const Variant **)argptrs, argc, ret);
2387
2388
ip += 3;
2389
}
2390
DISPATCH_OPCODE;
2391
2392
OPCODE(OPCODE_CALL_UTILITY) {
2393
LOAD_INSTRUCTION_ARGS
2394
CHECK_SPACE(3 + instr_arg_count);
2395
2396
ip += instr_arg_count;
2397
2398
int argc = _code_ptr[ip + 1];
2399
GD_ERR_BREAK(argc < 0);
2400
2401
GD_ERR_BREAK(_code_ptr[ip + 2] < 0 || _code_ptr[ip + 2] >= _global_names_count);
2402
StringName function = _global_names_ptr[_code_ptr[ip + 2]];
2403
2404
Variant **argptrs = instruction_args;
2405
2406
GET_INSTRUCTION_ARG(dst, argc);
2407
2408
Callable::CallError err;
2409
Variant::call_utility_function(function, dst, (const Variant **)argptrs, argc, err);
2410
2411
#ifdef DEBUG_ENABLED
2412
if (err.error != Callable::CallError::CALL_OK) {
2413
String methodstr = function;
2414
if (dst->get_type() == Variant::STRING && !dst->operator String().is_empty()) {
2415
// Call provided error string.
2416
err_text = vformat(R"*(Error calling utility function "%s()": %s)*", methodstr, *dst);
2417
} else {
2418
err_text = _get_call_error(vformat(R"*(utility function "%s()")*", methodstr), (const Variant **)argptrs, argc, *dst, err);
2419
}
2420
OPCODE_BREAK;
2421
}
2422
#endif
2423
ip += 3;
2424
}
2425
DISPATCH_OPCODE;
2426
2427
OPCODE(OPCODE_CALL_UTILITY_VALIDATED) {
2428
LOAD_INSTRUCTION_ARGS
2429
CHECK_SPACE(3 + instr_arg_count);
2430
2431
ip += instr_arg_count;
2432
2433
int argc = _code_ptr[ip + 1];
2434
GD_ERR_BREAK(argc < 0);
2435
2436
GD_ERR_BREAK(_code_ptr[ip + 2] < 0 || _code_ptr[ip + 2] >= _utilities_count);
2437
Variant::ValidatedUtilityFunction function = _utilities_ptr[_code_ptr[ip + 2]];
2438
2439
Variant **argptrs = instruction_args;
2440
2441
GET_INSTRUCTION_ARG(dst, argc);
2442
2443
function(dst, (const Variant **)argptrs, argc);
2444
2445
ip += 3;
2446
}
2447
DISPATCH_OPCODE;
2448
2449
OPCODE(OPCODE_CALL_GDSCRIPT_UTILITY) {
2450
LOAD_INSTRUCTION_ARGS
2451
CHECK_SPACE(3 + instr_arg_count);
2452
2453
ip += instr_arg_count;
2454
2455
int argc = _code_ptr[ip + 1];
2456
GD_ERR_BREAK(argc < 0);
2457
2458
GD_ERR_BREAK(_code_ptr[ip + 2] < 0 || _code_ptr[ip + 2] >= _gds_utilities_count);
2459
GDScriptUtilityFunctions::FunctionPtr function = _gds_utilities_ptr[_code_ptr[ip + 2]];
2460
2461
Variant **argptrs = instruction_args;
2462
2463
GET_INSTRUCTION_ARG(dst, argc);
2464
2465
Callable::CallError err;
2466
function(dst, (const Variant **)argptrs, argc, err);
2467
2468
#ifdef DEBUG_ENABLED
2469
if (err.error != Callable::CallError::CALL_OK) {
2470
String methodstr = gds_utilities_names[_code_ptr[ip + 2]];
2471
if (dst->get_type() == Variant::STRING && !dst->operator String().is_empty()) {
2472
// Call provided error string.
2473
err_text = vformat(R"*(Error calling GDScript utility function "%s()": %s)*", methodstr, *dst);
2474
} else {
2475
err_text = _get_call_error(vformat(R"*(GDScript utility function "%s()")*", methodstr), (const Variant **)argptrs, argc, *dst, err);
2476
}
2477
OPCODE_BREAK;
2478
}
2479
#endif
2480
ip += 3;
2481
}
2482
DISPATCH_OPCODE;
2483
2484
OPCODE(OPCODE_CALL_SELF_BASE) {
2485
LOAD_INSTRUCTION_ARGS
2486
CHECK_SPACE(3 + instr_arg_count);
2487
2488
ip += instr_arg_count;
2489
2490
int argc = _code_ptr[ip + 1];
2491
GD_ERR_BREAK(argc < 0);
2492
2493
int self_fun = _code_ptr[ip + 2];
2494
#ifdef DEBUG_ENABLED
2495
if (self_fun < 0 || self_fun >= _global_names_count) {
2496
err_text = "compiler bug, function name not found";
2497
OPCODE_BREAK;
2498
}
2499
#endif
2500
const StringName *methodname = &_global_names_ptr[self_fun];
2501
2502
GodotProfileZoneScriptSystemCall(methodname, source, name, *methodname, line);
2503
2504
Variant **argptrs = instruction_args;
2505
2506
GET_INSTRUCTION_ARG(dst, argc);
2507
2508
const GDScript *gds = _script;
2509
2510
HashMap<StringName, GDScriptFunction *>::ConstIterator E;
2511
while (gds->base.ptr()) {
2512
gds = gds->base.ptr();
2513
E = gds->member_functions.find(*methodname);
2514
if (E) {
2515
break;
2516
}
2517
}
2518
2519
Callable::CallError err;
2520
2521
if (E) {
2522
*dst = E->value->call(p_instance, (const Variant **)argptrs, argc, err);
2523
} else if (gds->native.ptr()) {
2524
if (*methodname != GDScriptLanguage::get_singleton()->strings._init) {
2525
MethodBind *mb = ClassDB::get_method(gds->native->get_name(), *methodname);
2526
if (!mb) {
2527
err.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
2528
} else {
2529
*dst = mb->call(p_instance->owner, (const Variant **)argptrs, argc, err);
2530
}
2531
} else {
2532
err.error = Callable::CallError::CALL_OK;
2533
}
2534
} else {
2535
if (*methodname != GDScriptLanguage::get_singleton()->strings._init) {
2536
err.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
2537
} else {
2538
err.error = Callable::CallError::CALL_OK;
2539
}
2540
}
2541
2542
if (err.error != Callable::CallError::CALL_OK) {
2543
String methodstr = *methodname;
2544
err_text = _get_call_error("function '" + methodstr + "'", (const Variant **)argptrs, argc, *dst, err);
2545
2546
OPCODE_BREAK;
2547
}
2548
2549
ip += 3;
2550
}
2551
DISPATCH_OPCODE;
2552
2553
OPCODE(OPCODE_AWAIT) {
2554
CHECK_SPACE(2);
2555
2556
// Do the one-shot connect.
2557
GET_VARIANT_PTR(argobj, 0);
2558
2559
Signal sig;
2560
bool is_signal = true;
2561
2562
{
2563
Variant result = *argobj;
2564
2565
if (argobj->get_type() == Variant::OBJECT) {
2566
bool was_freed = false;
2567
Object *obj = argobj->get_validated_object_with_check(was_freed);
2568
2569
if (was_freed) {
2570
err_text = "Trying to await on a freed object.";
2571
OPCODE_BREAK;
2572
}
2573
2574
// Is this even possible to be null at this point?
2575
if (obj) {
2576
if (obj->is_class_ptr(GDScriptFunctionState::get_class_ptr_static())) {
2577
result = Signal(obj, SNAME("completed"));
2578
}
2579
}
2580
}
2581
2582
if (result.get_type() != Variant::SIGNAL) {
2583
// Not async, return immediately using the target from OPCODE_AWAIT_RESUME.
2584
GET_VARIANT_PTR(target, 2);
2585
*target = result;
2586
ip += 4; // Skip OPCODE_AWAIT_RESUME and its data.
2587
is_signal = false;
2588
} else {
2589
sig = result;
2590
}
2591
}
2592
2593
if (is_signal) {
2594
Ref<GDScriptFunctionState> gdfs = memnew(GDScriptFunctionState);
2595
gdfs->function = this;
2596
2597
gdfs->state.stack.resize(alloca_size);
2598
2599
// First `FIXED_ADDRESSES_MAX` stack addresses are special, so we just skip them here.
2600
for (int i = FIXED_ADDRESSES_MAX; i < _stack_size; i++) {
2601
memnew_placement(&gdfs->state.stack.write[sizeof(Variant) * i], Variant(stack[i]));
2602
}
2603
gdfs->state.stack_size = _stack_size;
2604
gdfs->state.ip = ip + 2;
2605
gdfs->state.line = line;
2606
gdfs->state.script = _script;
2607
{
2608
MutexLock lock(GDScriptLanguage::get_singleton()->mutex);
2609
_script->pending_func_states.add(&gdfs->scripts_list);
2610
if (p_instance) {
2611
gdfs->state.instance = p_instance;
2612
p_instance->pending_func_states.add(&gdfs->instances_list);
2613
} else {
2614
gdfs->state.instance = nullptr;
2615
}
2616
}
2617
#ifdef DEBUG_ENABLED
2618
gdfs->state.function_name = name;
2619
gdfs->state.script_path = _script->get_script_path();
2620
#endif
2621
gdfs->state.defarg = defarg;
2622
gdfs->function = this;
2623
2624
if (p_state) {
2625
// Pass down the signal from the first state.
2626
gdfs->state.completed = p_state->completed;
2627
} else {
2628
gdfs->state.completed = Signal(gdfs.ptr(), SNAME("completed"));
2629
}
2630
2631
retvalue = gdfs;
2632
2633
Error err = sig.connect(Callable(gdfs.ptr(), "_signal_callback").bind(retvalue), Object::CONNECT_ONE_SHOT);
2634
if (err != OK) {
2635
err_text = "Error connecting to signal: " + sig.get_name() + " during await.";
2636
OPCODE_BREAK;
2637
}
2638
2639
awaited = true;
2640
2641
#ifdef DEBUG_ENABLED
2642
exit_ok = true;
2643
#endif
2644
OPCODE_BREAK;
2645
}
2646
}
2647
DISPATCH_OPCODE; // Needed for synchronous calls (when result is immediately available).
2648
2649
OPCODE(OPCODE_AWAIT_RESUME) {
2650
CHECK_SPACE(2);
2651
#ifdef DEBUG_ENABLED
2652
if (!p_state) {
2653
err_text = ("Invalid Resume (bug?)");
2654
OPCODE_BREAK;
2655
}
2656
#endif
2657
GET_VARIANT_PTR(result, 0);
2658
*result = p_state->result;
2659
ip += 2;
2660
}
2661
DISPATCH_OPCODE;
2662
2663
OPCODE(OPCODE_CREATE_LAMBDA) {
2664
LOAD_INSTRUCTION_ARGS
2665
CHECK_SPACE(2 + instr_arg_count);
2666
2667
ip += instr_arg_count;
2668
2669
int captures_count = _code_ptr[ip + 1];
2670
GD_ERR_BREAK(captures_count < 0);
2671
2672
int lambda_index = _code_ptr[ip + 2];
2673
GD_ERR_BREAK(lambda_index < 0 || lambda_index >= _lambdas_count);
2674
GDScriptFunction *lambda = _lambdas_ptr[lambda_index];
2675
2676
Vector<Variant> captures;
2677
captures.resize(captures_count);
2678
for (int i = 0; i < captures_count; i++) {
2679
GET_INSTRUCTION_ARG(arg, i);
2680
captures.write[i] = *arg;
2681
}
2682
2683
GDScriptLambdaCallable *callable = memnew(GDScriptLambdaCallable(Ref<GDScript>(script), lambda, captures));
2684
2685
GET_INSTRUCTION_ARG(result, captures_count);
2686
*result = Callable(callable);
2687
2688
ip += 3;
2689
}
2690
DISPATCH_OPCODE;
2691
2692
OPCODE(OPCODE_CREATE_SELF_LAMBDA) {
2693
LOAD_INSTRUCTION_ARGS
2694
CHECK_SPACE(2 + instr_arg_count);
2695
2696
GD_ERR_BREAK(p_instance == nullptr);
2697
2698
ip += instr_arg_count;
2699
2700
int captures_count = _code_ptr[ip + 1];
2701
GD_ERR_BREAK(captures_count < 0);
2702
2703
int lambda_index = _code_ptr[ip + 2];
2704
GD_ERR_BREAK(lambda_index < 0 || lambda_index >= _lambdas_count);
2705
GDScriptFunction *lambda = _lambdas_ptr[lambda_index];
2706
2707
Vector<Variant> captures;
2708
captures.resize(captures_count);
2709
for (int i = 0; i < captures_count; i++) {
2710
GET_INSTRUCTION_ARG(arg, i);
2711
captures.write[i] = *arg;
2712
}
2713
2714
GDScriptLambdaSelfCallable *callable;
2715
if (Object::cast_to<RefCounted>(p_instance->owner)) {
2716
callable = memnew(GDScriptLambdaSelfCallable(Ref<RefCounted>(Object::cast_to<RefCounted>(p_instance->owner)), lambda, captures));
2717
} else {
2718
callable = memnew(GDScriptLambdaSelfCallable(p_instance->owner, lambda, captures));
2719
}
2720
2721
GET_INSTRUCTION_ARG(result, captures_count);
2722
*result = Callable(callable);
2723
2724
ip += 3;
2725
}
2726
DISPATCH_OPCODE;
2727
2728
OPCODE(OPCODE_JUMP) {
2729
CHECK_SPACE(2);
2730
int to = _code_ptr[ip + 1];
2731
2732
GD_ERR_BREAK(to < 0 || to > _code_size);
2733
ip = to;
2734
}
2735
DISPATCH_OPCODE;
2736
2737
OPCODE(OPCODE_JUMP_IF) {
2738
CHECK_SPACE(3);
2739
2740
GET_VARIANT_PTR(test, 0);
2741
2742
bool result = test->booleanize();
2743
2744
if (result) {
2745
int to = _code_ptr[ip + 2];
2746
GD_ERR_BREAK(to < 0 || to > _code_size);
2747
ip = to;
2748
} else {
2749
ip += 3;
2750
}
2751
}
2752
DISPATCH_OPCODE;
2753
2754
OPCODE(OPCODE_JUMP_IF_NOT) {
2755
CHECK_SPACE(3);
2756
2757
GET_VARIANT_PTR(test, 0);
2758
2759
bool result = test->booleanize();
2760
2761
if (!result) {
2762
int to = _code_ptr[ip + 2];
2763
GD_ERR_BREAK(to < 0 || to > _code_size);
2764
ip = to;
2765
} else {
2766
ip += 3;
2767
}
2768
}
2769
DISPATCH_OPCODE;
2770
2771
OPCODE(OPCODE_JUMP_TO_DEF_ARGUMENT) {
2772
CHECK_SPACE(2);
2773
ip = _default_arg_ptr[defarg];
2774
}
2775
DISPATCH_OPCODE;
2776
2777
OPCODE(OPCODE_JUMP_IF_SHARED) {
2778
CHECK_SPACE(3);
2779
2780
GET_VARIANT_PTR(val, 0);
2781
2782
if (val->is_shared()) {
2783
int to = _code_ptr[ip + 2];
2784
GD_ERR_BREAK(to < 0 || to > _code_size);
2785
ip = to;
2786
} else {
2787
ip += 3;
2788
}
2789
}
2790
DISPATCH_OPCODE;
2791
2792
OPCODE(OPCODE_RETURN) {
2793
CHECK_SPACE(2);
2794
GET_VARIANT_PTR(r, 0);
2795
retvalue = *r;
2796
#ifdef DEBUG_ENABLED
2797
exit_ok = true;
2798
#endif
2799
OPCODE_BREAK;
2800
}
2801
2802
OPCODE(OPCODE_RETURN_TYPED_BUILTIN) {
2803
CHECK_SPACE(3);
2804
GET_VARIANT_PTR(r, 0);
2805
2806
Variant::Type ret_type = (Variant::Type)_code_ptr[ip + 2];
2807
GD_ERR_BREAK(ret_type < 0 || ret_type >= Variant::VARIANT_MAX);
2808
2809
if (r->get_type() != ret_type) {
2810
if (Variant::can_convert_strict(r->get_type(), ret_type)) {
2811
Callable::CallError ce;
2812
Variant::construct(ret_type, retvalue, const_cast<const Variant **>(&r), 1, ce);
2813
} else {
2814
#ifdef DEBUG_ENABLED
2815
err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)",
2816
Variant::get_type_name(r->get_type()), Variant::get_type_name(ret_type));
2817
#endif // DEBUG_ENABLED
2818
2819
// Construct a base type anyway so type constraints are met.
2820
Callable::CallError ce;
2821
Variant::construct(ret_type, retvalue, nullptr, 0, ce);
2822
OPCODE_BREAK;
2823
}
2824
} else {
2825
retvalue = *r;
2826
}
2827
#ifdef DEBUG_ENABLED
2828
exit_ok = true;
2829
#endif // DEBUG_ENABLED
2830
OPCODE_BREAK;
2831
}
2832
2833
OPCODE(OPCODE_RETURN_TYPED_ARRAY) {
2834
CHECK_SPACE(5);
2835
GET_VARIANT_PTR(r, 0);
2836
2837
GET_VARIANT_PTR(script_type, 1);
2838
Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + 3];
2839
int native_type_idx = _code_ptr[ip + 4];
2840
GD_ERR_BREAK(native_type_idx < 0 || native_type_idx >= _global_names_count);
2841
const StringName native_type = _global_names_ptr[native_type_idx];
2842
2843
if (r->get_type() != Variant::ARRAY) {
2844
#ifdef DEBUG_ENABLED
2845
err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "Array[%s]".)",
2846
Variant::get_type_name(r->get_type()), Variant::get_type_name(builtin_type));
2847
#endif
2848
OPCODE_BREAK;
2849
}
2850
2851
Array *array = VariantInternal::get_array(r);
2852
2853
if (array->get_typed_builtin() != ((uint32_t)builtin_type) || array->get_typed_class_name() != native_type || array->get_typed_script() != *script_type) {
2854
#ifdef DEBUG_ENABLED
2855
err_text = vformat(R"(Trying to return an array of type "%s" where expected return type is "Array[%s]".)",
2856
_get_var_type(r), _get_element_type(builtin_type, native_type, *script_type));
2857
#endif // DEBUG_ENABLED
2858
OPCODE_BREAK;
2859
}
2860
2861
retvalue = *array;
2862
2863
#ifdef DEBUG_ENABLED
2864
exit_ok = true;
2865
#endif // DEBUG_ENABLED
2866
OPCODE_BREAK;
2867
}
2868
2869
OPCODE(OPCODE_RETURN_TYPED_DICTIONARY) {
2870
CHECK_SPACE(8);
2871
GET_VARIANT_PTR(r, 0);
2872
2873
GET_VARIANT_PTR(key_script_type, 1);
2874
Variant::Type key_builtin_type = (Variant::Type)_code_ptr[ip + 4];
2875
int key_native_type_idx = _code_ptr[ip + 5];
2876
GD_ERR_BREAK(key_native_type_idx < 0 || key_native_type_idx >= _global_names_count);
2877
const StringName key_native_type = _global_names_ptr[key_native_type_idx];
2878
2879
GET_VARIANT_PTR(value_script_type, 2);
2880
Variant::Type value_builtin_type = (Variant::Type)_code_ptr[ip + 6];
2881
int value_native_type_idx = _code_ptr[ip + 7];
2882
GD_ERR_BREAK(value_native_type_idx < 0 || value_native_type_idx >= _global_names_count);
2883
const StringName value_native_type = _global_names_ptr[value_native_type_idx];
2884
2885
if (r->get_type() != Variant::DICTIONARY) {
2886
#ifdef DEBUG_ENABLED
2887
err_text = vformat(R"(Trying to return a value of type "%s" where expected return type is "Dictionary[%s, %s]".)",
2888
_get_var_type(r), _get_element_type(key_builtin_type, key_native_type, *key_script_type),
2889
_get_element_type(value_builtin_type, value_native_type, *value_script_type));
2890
#endif // DEBUG_ENABLED
2891
OPCODE_BREAK;
2892
}
2893
2894
Dictionary *dictionary = VariantInternal::get_dictionary(r);
2895
2896
if (dictionary->get_typed_key_builtin() != ((uint32_t)key_builtin_type) || dictionary->get_typed_key_class_name() != key_native_type || dictionary->get_typed_key_script() != *key_script_type ||
2897
dictionary->get_typed_value_builtin() != ((uint32_t)value_builtin_type) || dictionary->get_typed_value_class_name() != value_native_type || dictionary->get_typed_value_script() != *value_script_type) {
2898
#ifdef DEBUG_ENABLED
2899
err_text = vformat(R"(Trying to return a dictionary of type "%s" where expected return type is "Dictionary[%s, %s]".)",
2900
_get_var_type(r), _get_element_type(key_builtin_type, key_native_type, *key_script_type),
2901
_get_element_type(value_builtin_type, value_native_type, *value_script_type));
2902
#endif // DEBUG_ENABLED
2903
OPCODE_BREAK;
2904
}
2905
2906
retvalue = *dictionary;
2907
2908
#ifdef DEBUG_ENABLED
2909
exit_ok = true;
2910
#endif // DEBUG_ENABLED
2911
OPCODE_BREAK;
2912
}
2913
2914
OPCODE(OPCODE_RETURN_TYPED_NATIVE) {
2915
CHECK_SPACE(3);
2916
GET_VARIANT_PTR(r, 0);
2917
2918
GET_VARIANT_PTR(type, 1);
2919
GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(type->operator Object *());
2920
GD_ERR_BREAK(!nc);
2921
2922
if (r->get_type() != Variant::OBJECT && r->get_type() != Variant::NIL) {
2923
err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)",
2924
Variant::get_type_name(r->get_type()), nc->get_name());
2925
OPCODE_BREAK;
2926
}
2927
2928
#ifdef DEBUG_ENABLED
2929
bool freed = false;
2930
Object *ret_obj = r->get_validated_object_with_check(freed);
2931
2932
if (freed) {
2933
err_text = "Trying to return a previously freed instance.";
2934
OPCODE_BREAK;
2935
}
2936
#else
2937
Object *ret_obj = r->operator Object *();
2938
#endif // DEBUG_ENABLED
2939
if (ret_obj && !ClassDB::is_parent_class(ret_obj->get_class_name(), nc->get_name())) {
2940
#ifdef DEBUG_ENABLED
2941
err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)",
2942
ret_obj->get_class_name(), nc->get_name());
2943
#endif // DEBUG_ENABLED
2944
OPCODE_BREAK;
2945
}
2946
retvalue = *r;
2947
2948
#ifdef DEBUG_ENABLED
2949
exit_ok = true;
2950
#endif // DEBUG_ENABLED
2951
OPCODE_BREAK;
2952
}
2953
2954
OPCODE(OPCODE_RETURN_TYPED_SCRIPT) {
2955
CHECK_SPACE(3);
2956
GET_VARIANT_PTR(r, 0);
2957
2958
GET_VARIANT_PTR(type, 1);
2959
Script *base_type = Object::cast_to<Script>(type->operator Object *());
2960
GD_ERR_BREAK(!base_type);
2961
2962
if (r->get_type() != Variant::OBJECT && r->get_type() != Variant::NIL) {
2963
#ifdef DEBUG_ENABLED
2964
err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)",
2965
Variant::get_type_name(r->get_type()), GDScript::debug_get_script_name(Ref<Script>(base_type)));
2966
#endif // DEBUG_ENABLED
2967
OPCODE_BREAK;
2968
}
2969
2970
#ifdef DEBUG_ENABLED
2971
bool freed = false;
2972
Object *ret_obj = r->get_validated_object_with_check(freed);
2973
2974
if (freed) {
2975
err_text = "Trying to return a previously freed instance.";
2976
OPCODE_BREAK;
2977
}
2978
#else
2979
Object *ret_obj = r->operator Object *();
2980
#endif // DEBUG_ENABLED
2981
2982
if (ret_obj) {
2983
ScriptInstance *ret_inst = ret_obj->get_script_instance();
2984
if (!ret_inst) {
2985
#ifdef DEBUG_ENABLED
2986
err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)",
2987
ret_obj->get_class_name(), GDScript::debug_get_script_name(Ref<GDScript>(base_type)));
2988
#endif // DEBUG_ENABLED
2989
OPCODE_BREAK;
2990
}
2991
2992
Script *ret_type = ret_obj->get_script_instance()->get_script().ptr();
2993
bool valid = false;
2994
2995
while (ret_type) {
2996
if (ret_type == base_type) {
2997
valid = true;
2998
break;
2999
}
3000
ret_type = ret_type->get_base_script().ptr();
3001
}
3002
3003
if (!valid) {
3004
#ifdef DEBUG_ENABLED
3005
err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)",
3006
GDScript::debug_get_script_name(ret_obj->get_script_instance()->get_script()), GDScript::debug_get_script_name(Ref<GDScript>(base_type)));
3007
#endif // DEBUG_ENABLED
3008
OPCODE_BREAK;
3009
}
3010
}
3011
retvalue = *r;
3012
3013
#ifdef DEBUG_ENABLED
3014
exit_ok = true;
3015
#endif // DEBUG_ENABLED
3016
OPCODE_BREAK;
3017
}
3018
3019
OPCODE(OPCODE_ITERATE_BEGIN) {
3020
CHECK_SPACE(8); // Space for this and a regular iterate.
3021
3022
GET_VARIANT_PTR(counter, 0);
3023
GET_VARIANT_PTR(container, 1);
3024
3025
*counter = Variant();
3026
3027
bool valid;
3028
if (!container->iter_init(*counter, valid)) {
3029
#ifdef DEBUG_ENABLED
3030
if (!valid) {
3031
err_text = "Unable to iterate on object of type '" + Variant::get_type_name(container->get_type()) + "'.";
3032
OPCODE_BREAK;
3033
}
3034
#endif
3035
int jumpto = _code_ptr[ip + 4];
3036
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3037
ip = jumpto;
3038
} else {
3039
GET_VARIANT_PTR(iterator, 2);
3040
3041
*iterator = container->iter_get(*counter, valid);
3042
#ifdef DEBUG_ENABLED
3043
if (!valid) {
3044
err_text = "Unable to obtain iterator object of type '" + Variant::get_type_name(container->get_type()) + "'.";
3045
OPCODE_BREAK;
3046
}
3047
#endif
3048
ip += 5; // Skip regular iterate which is always next.
3049
}
3050
}
3051
DISPATCH_OPCODE;
3052
3053
OPCODE(OPCODE_ITERATE_BEGIN_INT) {
3054
CHECK_SPACE(8); // Check space for iterate instruction too.
3055
3056
GET_VARIANT_PTR(counter, 0);
3057
GET_VARIANT_PTR(container, 1);
3058
3059
int64_t size = *VariantInternal::get_int(container);
3060
3061
VariantInternal::initialize(counter, Variant::INT);
3062
*VariantInternal::get_int(counter) = 0;
3063
3064
if (size > 0) {
3065
GET_VARIANT_PTR(iterator, 2);
3066
VariantInternal::initialize(iterator, Variant::INT);
3067
*VariantInternal::get_int(iterator) = 0;
3068
3069
// Skip regular iterate.
3070
ip += 5;
3071
} else {
3072
// Jump to end of loop.
3073
int jumpto = _code_ptr[ip + 4];
3074
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3075
ip = jumpto;
3076
}
3077
}
3078
DISPATCH_OPCODE;
3079
3080
OPCODE(OPCODE_ITERATE_BEGIN_FLOAT) {
3081
CHECK_SPACE(8); // Check space for iterate instruction too.
3082
3083
GET_VARIANT_PTR(counter, 0);
3084
GET_VARIANT_PTR(container, 1);
3085
3086
double size = *VariantInternal::get_float(container);
3087
3088
VariantInternal::initialize(counter, Variant::FLOAT);
3089
*VariantInternal::get_float(counter) = 0.0;
3090
3091
if (size > 0) {
3092
GET_VARIANT_PTR(iterator, 2);
3093
VariantInternal::initialize(iterator, Variant::FLOAT);
3094
*VariantInternal::get_float(iterator) = 0;
3095
3096
// Skip regular iterate.
3097
ip += 5;
3098
} else {
3099
// Jump to end of loop.
3100
int jumpto = _code_ptr[ip + 4];
3101
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3102
ip = jumpto;
3103
}
3104
}
3105
DISPATCH_OPCODE;
3106
3107
OPCODE(OPCODE_ITERATE_BEGIN_VECTOR2) {
3108
CHECK_SPACE(8); // Check space for iterate instruction too.
3109
3110
GET_VARIANT_PTR(counter, 0);
3111
GET_VARIANT_PTR(container, 1);
3112
3113
Vector2 *bounds = VariantInternal::get_vector2(container);
3114
3115
VariantInternal::initialize(counter, Variant::FLOAT);
3116
*VariantInternal::get_float(counter) = bounds->x;
3117
3118
if (bounds->x < bounds->y) {
3119
GET_VARIANT_PTR(iterator, 2);
3120
VariantInternal::initialize(iterator, Variant::FLOAT);
3121
*VariantInternal::get_float(iterator) = bounds->x;
3122
3123
// Skip regular iterate.
3124
ip += 5;
3125
} else {
3126
// Jump to end of loop.
3127
int jumpto = _code_ptr[ip + 4];
3128
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3129
ip = jumpto;
3130
}
3131
}
3132
DISPATCH_OPCODE;
3133
3134
OPCODE(OPCODE_ITERATE_BEGIN_VECTOR2I) {
3135
CHECK_SPACE(8); // Check space for iterate instruction too.
3136
3137
GET_VARIANT_PTR(counter, 0);
3138
GET_VARIANT_PTR(container, 1);
3139
3140
Vector2i *bounds = VariantInternal::get_vector2i(container);
3141
3142
VariantInternal::initialize(counter, Variant::FLOAT);
3143
*VariantInternal::get_int(counter) = bounds->x;
3144
3145
if (bounds->x < bounds->y) {
3146
GET_VARIANT_PTR(iterator, 2);
3147
VariantInternal::initialize(iterator, Variant::INT);
3148
*VariantInternal::get_int(iterator) = bounds->x;
3149
3150
// Skip regular iterate.
3151
ip += 5;
3152
} else {
3153
// Jump to end of loop.
3154
int jumpto = _code_ptr[ip + 4];
3155
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3156
ip = jumpto;
3157
}
3158
}
3159
DISPATCH_OPCODE;
3160
3161
OPCODE(OPCODE_ITERATE_BEGIN_VECTOR3) {
3162
CHECK_SPACE(8); // Check space for iterate instruction too.
3163
3164
GET_VARIANT_PTR(counter, 0);
3165
GET_VARIANT_PTR(container, 1);
3166
3167
Vector3 *bounds = VariantInternal::get_vector3(container);
3168
double from = bounds->x;
3169
double to = bounds->y;
3170
double step = bounds->z;
3171
3172
VariantInternal::initialize(counter, Variant::FLOAT);
3173
*VariantInternal::get_float(counter) = from;
3174
3175
bool do_continue = from == to ? false : (from < to ? step > 0 : step < 0);
3176
3177
if (do_continue) {
3178
GET_VARIANT_PTR(iterator, 2);
3179
VariantInternal::initialize(iterator, Variant::FLOAT);
3180
*VariantInternal::get_float(iterator) = from;
3181
3182
// Skip regular iterate.
3183
ip += 5;
3184
} else {
3185
// Jump to end of loop.
3186
int jumpto = _code_ptr[ip + 4];
3187
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3188
ip = jumpto;
3189
}
3190
}
3191
DISPATCH_OPCODE;
3192
3193
OPCODE(OPCODE_ITERATE_BEGIN_VECTOR3I) {
3194
CHECK_SPACE(8); // Check space for iterate instruction too.
3195
3196
GET_VARIANT_PTR(counter, 0);
3197
GET_VARIANT_PTR(container, 1);
3198
3199
Vector3i *bounds = VariantInternal::get_vector3i(container);
3200
int64_t from = bounds->x;
3201
int64_t to = bounds->y;
3202
int64_t step = bounds->z;
3203
3204
VariantInternal::initialize(counter, Variant::INT);
3205
*VariantInternal::get_int(counter) = from;
3206
3207
bool do_continue = from == to ? false : (from < to ? step > 0 : step < 0);
3208
3209
if (do_continue) {
3210
GET_VARIANT_PTR(iterator, 2);
3211
VariantInternal::initialize(iterator, Variant::INT);
3212
*VariantInternal::get_int(iterator) = from;
3213
3214
// Skip regular iterate.
3215
ip += 5;
3216
} else {
3217
// Jump to end of loop.
3218
int jumpto = _code_ptr[ip + 4];
3219
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3220
ip = jumpto;
3221
}
3222
}
3223
DISPATCH_OPCODE;
3224
3225
OPCODE(OPCODE_ITERATE_BEGIN_STRING) {
3226
CHECK_SPACE(8); // Check space for iterate instruction too.
3227
3228
GET_VARIANT_PTR(counter, 0);
3229
GET_VARIANT_PTR(container, 1);
3230
3231
String *str = VariantInternal::get_string(container);
3232
3233
VariantInternal::initialize(counter, Variant::INT);
3234
*VariantInternal::get_int(counter) = 0;
3235
3236
if (!str->is_empty()) {
3237
GET_VARIANT_PTR(iterator, 2);
3238
VariantInternal::initialize(iterator, Variant::STRING);
3239
*VariantInternal::get_string(iterator) = str->substr(0, 1);
3240
3241
// Skip regular iterate.
3242
ip += 5;
3243
} else {
3244
// Jump to end of loop.
3245
int jumpto = _code_ptr[ip + 4];
3246
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3247
ip = jumpto;
3248
}
3249
}
3250
DISPATCH_OPCODE;
3251
3252
OPCODE(OPCODE_ITERATE_BEGIN_DICTIONARY) {
3253
CHECK_SPACE(8); // Check space for iterate instruction too.
3254
3255
GET_VARIANT_PTR(counter, 0);
3256
GET_VARIANT_PTR(container, 1);
3257
3258
Dictionary *dict = VariantInternal::get_dictionary(container);
3259
const Variant *next = dict->next(nullptr);
3260
3261
if (!dict->is_empty()) {
3262
GET_VARIANT_PTR(iterator, 2);
3263
*counter = *next;
3264
*iterator = *next;
3265
3266
// Skip regular iterate.
3267
ip += 5;
3268
} else {
3269
// Jump to end of loop.
3270
int jumpto = _code_ptr[ip + 4];
3271
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3272
ip = jumpto;
3273
}
3274
}
3275
DISPATCH_OPCODE;
3276
3277
OPCODE(OPCODE_ITERATE_BEGIN_ARRAY) {
3278
CHECK_SPACE(8); // Check space for iterate instruction too.
3279
3280
GET_VARIANT_PTR(counter, 0);
3281
GET_VARIANT_PTR(container, 1);
3282
3283
Array *array = VariantInternal::get_array(container);
3284
3285
VariantInternal::initialize(counter, Variant::INT);
3286
*VariantInternal::get_int(counter) = 0;
3287
3288
if (!array->is_empty()) {
3289
GET_VARIANT_PTR(iterator, 2);
3290
*iterator = array->get(0);
3291
3292
// Skip regular iterate.
3293
ip += 5;
3294
} else {
3295
// Jump to end of loop.
3296
int jumpto = _code_ptr[ip + 4];
3297
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3298
ip = jumpto;
3299
}
3300
}
3301
DISPATCH_OPCODE;
3302
3303
#define OPCODE_ITERATE_BEGIN_PACKED_ARRAY(m_var_type, m_elem_type, m_get_func, m_var_ret_type, m_ret_type, m_ret_get_func) \
3304
OPCODE(OPCODE_ITERATE_BEGIN_PACKED_##m_var_type##_ARRAY) { \
3305
CHECK_SPACE(8); \
3306
GET_VARIANT_PTR(counter, 0); \
3307
GET_VARIANT_PTR(container, 1); \
3308
Vector<m_elem_type> *array = VariantInternal::m_get_func(container); \
3309
VariantInternal::initialize(counter, Variant::INT); \
3310
*VariantInternal::get_int(counter) = 0; \
3311
if (!array->is_empty()) { \
3312
GET_VARIANT_PTR(iterator, 2); \
3313
VariantInternal::initialize(iterator, Variant::m_var_ret_type); \
3314
m_ret_type *it = VariantInternal::m_ret_get_func(iterator); \
3315
*it = array->get(0); \
3316
ip += 5; \
3317
} else { \
3318
int jumpto = _code_ptr[ip + 4]; \
3319
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size); \
3320
ip = jumpto; \
3321
} \
3322
} \
3323
DISPATCH_OPCODE
3324
3325
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(BYTE, uint8_t, get_byte_array, INT, int64_t, get_int);
3326
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(INT32, int32_t, get_int32_array, INT, int64_t, get_int);
3327
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(INT64, int64_t, get_int64_array, INT, int64_t, get_int);
3328
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(FLOAT32, float, get_float32_array, FLOAT, double, get_float);
3329
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(FLOAT64, double, get_float64_array, FLOAT, double, get_float);
3330
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(STRING, String, get_string_array, STRING, String, get_string);
3331
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(VECTOR2, Vector2, get_vector2_array, VECTOR2, Vector2, get_vector2);
3332
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(VECTOR3, Vector3, get_vector3_array, VECTOR3, Vector3, get_vector3);
3333
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(COLOR, Color, get_color_array, COLOR, Color, get_color);
3334
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(VECTOR4, Vector4, get_vector4_array, VECTOR4, Vector4, get_vector4);
3335
3336
OPCODE(OPCODE_ITERATE_BEGIN_OBJECT) {
3337
CHECK_SPACE(4);
3338
3339
GET_VARIANT_PTR(counter, 0);
3340
GET_VARIANT_PTR(container, 1);
3341
3342
#ifdef DEBUG_ENABLED
3343
bool freed = false;
3344
Object *obj = container->get_validated_object_with_check(freed);
3345
if (freed) {
3346
err_text = "Trying to iterate on a previously freed object.";
3347
OPCODE_BREAK;
3348
} else if (!obj) {
3349
err_text = "Trying to iterate on a null value.";
3350
OPCODE_BREAK;
3351
}
3352
#else
3353
Object *obj = *VariantInternal::get_object(container);
3354
#endif
3355
3356
*counter = Variant();
3357
Array ref = { *counter };
3358
Variant vref;
3359
VariantInternal::initialize(&vref, Variant::ARRAY);
3360
*VariantInternal::get_array(&vref) = ref;
3361
3362
const Variant *args[] = { &vref };
3363
3364
Callable::CallError ce;
3365
Variant has_next = obj->callp(CoreStringName(_iter_init), args, 1, ce);
3366
3367
#ifdef DEBUG_ENABLED
3368
if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) {
3369
err_text = vformat(R"(There was an error calling "_iter_next" on iterator object of type %s.)", *container);
3370
OPCODE_BREAK;
3371
}
3372
#endif
3373
if (!has_next.booleanize()) {
3374
int jumpto = _code_ptr[ip + 4];
3375
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3376
ip = jumpto;
3377
} else {
3378
*counter = ref[0];
3379
3380
GET_VARIANT_PTR(iterator, 2);
3381
*iterator = obj->callp(CoreStringName(_iter_get), (const Variant **)&counter, 1, ce);
3382
#ifdef DEBUG_ENABLED
3383
if (ce.error != Callable::CallError::CALL_OK) {
3384
err_text = vformat(R"(There was an error calling "_iter_get" on iterator object of type %s.)", *container);
3385
OPCODE_BREAK;
3386
}
3387
#endif
3388
3389
ip += 5; // Loop again.
3390
}
3391
}
3392
DISPATCH_OPCODE;
3393
3394
OPCODE(OPCODE_ITERATE_BEGIN_RANGE) {
3395
CHECK_SPACE(6);
3396
3397
GET_VARIANT_PTR(counter, 0);
3398
GET_VARIANT_PTR(from_ptr, 1);
3399
GET_VARIANT_PTR(to_ptr, 2);
3400
GET_VARIANT_PTR(step_ptr, 3);
3401
3402
int64_t from = *VariantInternal::get_int(from_ptr);
3403
int64_t to = *VariantInternal::get_int(to_ptr);
3404
int64_t step = *VariantInternal::get_int(step_ptr);
3405
3406
VariantInternal::initialize(counter, Variant::INT);
3407
*VariantInternal::get_int(counter) = from;
3408
3409
bool do_continue = from == to ? false : (from < to ? step > 0 : step < 0);
3410
3411
if (do_continue) {
3412
GET_VARIANT_PTR(iterator, 4);
3413
VariantInternal::initialize(iterator, Variant::INT);
3414
*VariantInternal::get_int(iterator) = from;
3415
3416
// Skip regular iterate.
3417
ip += 7;
3418
} else {
3419
// Jump to end of loop.
3420
int jumpto = _code_ptr[ip + 6];
3421
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3422
ip = jumpto;
3423
}
3424
}
3425
DISPATCH_OPCODE;
3426
3427
OPCODE(OPCODE_ITERATE) {
3428
CHECK_SPACE(4);
3429
3430
GET_VARIANT_PTR(counter, 0);
3431
GET_VARIANT_PTR(container, 1);
3432
3433
bool valid;
3434
if (!container->iter_next(*counter, valid)) {
3435
#ifdef DEBUG_ENABLED
3436
if (!valid) {
3437
err_text = "Unable to iterate on object of type '" + Variant::get_type_name(container->get_type()) + "' (type changed since first iteration?).";
3438
OPCODE_BREAK;
3439
}
3440
#endif
3441
int jumpto = _code_ptr[ip + 4];
3442
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3443
ip = jumpto;
3444
} else {
3445
GET_VARIANT_PTR(iterator, 2);
3446
3447
*iterator = container->iter_get(*counter, valid);
3448
#ifdef DEBUG_ENABLED
3449
if (!valid) {
3450
err_text = "Unable to obtain iterator object of type '" + Variant::get_type_name(container->get_type()) + "' (but was obtained on first iteration?).";
3451
OPCODE_BREAK;
3452
}
3453
#endif
3454
ip += 5; //loop again
3455
}
3456
}
3457
DISPATCH_OPCODE;
3458
3459
OPCODE(OPCODE_ITERATE_INT) {
3460
CHECK_SPACE(4);
3461
3462
GET_VARIANT_PTR(counter, 0);
3463
GET_VARIANT_PTR(container, 1);
3464
3465
int64_t size = *VariantInternal::get_int(container);
3466
int64_t *count = VariantInternal::get_int(counter);
3467
3468
(*count)++;
3469
3470
if (*count >= size) {
3471
int jumpto = _code_ptr[ip + 4];
3472
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3473
ip = jumpto;
3474
} else {
3475
GET_VARIANT_PTR(iterator, 2);
3476
*VariantInternal::get_int(iterator) = *count;
3477
3478
ip += 5; // Loop again.
3479
}
3480
}
3481
DISPATCH_OPCODE;
3482
3483
OPCODE(OPCODE_ITERATE_FLOAT) {
3484
CHECK_SPACE(4);
3485
3486
GET_VARIANT_PTR(counter, 0);
3487
GET_VARIANT_PTR(container, 1);
3488
3489
double size = *VariantInternal::get_float(container);
3490
double *count = VariantInternal::get_float(counter);
3491
3492
(*count)++;
3493
3494
if (*count >= size) {
3495
int jumpto = _code_ptr[ip + 4];
3496
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3497
ip = jumpto;
3498
} else {
3499
GET_VARIANT_PTR(iterator, 2);
3500
*VariantInternal::get_float(iterator) = *count;
3501
3502
ip += 5; // Loop again.
3503
}
3504
}
3505
DISPATCH_OPCODE;
3506
3507
OPCODE(OPCODE_ITERATE_VECTOR2) {
3508
CHECK_SPACE(4);
3509
3510
GET_VARIANT_PTR(counter, 0);
3511
GET_VARIANT_PTR(container, 1);
3512
3513
const Vector2 *bounds = VariantInternal::get_vector2((const Variant *)container);
3514
double *count = VariantInternal::get_float(counter);
3515
3516
(*count)++;
3517
3518
if (*count >= bounds->y) {
3519
int jumpto = _code_ptr[ip + 4];
3520
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3521
ip = jumpto;
3522
} else {
3523
GET_VARIANT_PTR(iterator, 2);
3524
*VariantInternal::get_float(iterator) = *count;
3525
3526
ip += 5; // Loop again.
3527
}
3528
}
3529
DISPATCH_OPCODE;
3530
3531
OPCODE(OPCODE_ITERATE_VECTOR2I) {
3532
CHECK_SPACE(4);
3533
3534
GET_VARIANT_PTR(counter, 0);
3535
GET_VARIANT_PTR(container, 1);
3536
3537
const Vector2i *bounds = VariantInternal::get_vector2i((const Variant *)container);
3538
int64_t *count = VariantInternal::get_int(counter);
3539
3540
(*count)++;
3541
3542
if (*count >= bounds->y) {
3543
int jumpto = _code_ptr[ip + 4];
3544
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3545
ip = jumpto;
3546
} else {
3547
GET_VARIANT_PTR(iterator, 2);
3548
*VariantInternal::get_int(iterator) = *count;
3549
3550
ip += 5; // Loop again.
3551
}
3552
}
3553
DISPATCH_OPCODE;
3554
3555
OPCODE(OPCODE_ITERATE_VECTOR3) {
3556
CHECK_SPACE(4);
3557
3558
GET_VARIANT_PTR(counter, 0);
3559
GET_VARIANT_PTR(container, 1);
3560
3561
const Vector3 *bounds = VariantInternal::get_vector3((const Variant *)container);
3562
double *count = VariantInternal::get_float(counter);
3563
3564
*count += bounds->z;
3565
3566
if ((bounds->z < 0 && *count <= bounds->y) || (bounds->z > 0 && *count >= bounds->y)) {
3567
int jumpto = _code_ptr[ip + 4];
3568
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3569
ip = jumpto;
3570
} else {
3571
GET_VARIANT_PTR(iterator, 2);
3572
*VariantInternal::get_float(iterator) = *count;
3573
3574
ip += 5; // Loop again.
3575
}
3576
}
3577
DISPATCH_OPCODE;
3578
3579
OPCODE(OPCODE_ITERATE_VECTOR3I) {
3580
CHECK_SPACE(4);
3581
3582
GET_VARIANT_PTR(counter, 0);
3583
GET_VARIANT_PTR(container, 1);
3584
3585
const Vector3i *bounds = VariantInternal::get_vector3i((const Variant *)container);
3586
int64_t *count = VariantInternal::get_int(counter);
3587
3588
*count += bounds->z;
3589
3590
if ((bounds->z < 0 && *count <= bounds->y) || (bounds->z > 0 && *count >= bounds->y)) {
3591
int jumpto = _code_ptr[ip + 4];
3592
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3593
ip = jumpto;
3594
} else {
3595
GET_VARIANT_PTR(iterator, 2);
3596
*VariantInternal::get_int(iterator) = *count;
3597
3598
ip += 5; // Loop again.
3599
}
3600
}
3601
DISPATCH_OPCODE;
3602
3603
OPCODE(OPCODE_ITERATE_STRING) {
3604
CHECK_SPACE(4);
3605
3606
GET_VARIANT_PTR(counter, 0);
3607
GET_VARIANT_PTR(container, 1);
3608
3609
const String *str = VariantInternal::get_string((const Variant *)container);
3610
int64_t *idx = VariantInternal::get_int(counter);
3611
(*idx)++;
3612
3613
if (*idx >= str->length()) {
3614
int jumpto = _code_ptr[ip + 4];
3615
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3616
ip = jumpto;
3617
} else {
3618
GET_VARIANT_PTR(iterator, 2);
3619
*VariantInternal::get_string(iterator) = str->substr(*idx, 1);
3620
3621
ip += 5; // Loop again.
3622
}
3623
}
3624
DISPATCH_OPCODE;
3625
3626
OPCODE(OPCODE_ITERATE_DICTIONARY) {
3627
CHECK_SPACE(4);
3628
3629
GET_VARIANT_PTR(counter, 0);
3630
GET_VARIANT_PTR(container, 1);
3631
3632
const Dictionary *dict = VariantInternal::get_dictionary((const Variant *)container);
3633
const Variant *next = dict->next(counter);
3634
3635
if (!next) {
3636
int jumpto = _code_ptr[ip + 4];
3637
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3638
ip = jumpto;
3639
} else {
3640
GET_VARIANT_PTR(iterator, 2);
3641
*counter = *next;
3642
*iterator = *next;
3643
3644
ip += 5; // Loop again.
3645
}
3646
}
3647
DISPATCH_OPCODE;
3648
3649
OPCODE(OPCODE_ITERATE_ARRAY) {
3650
CHECK_SPACE(4);
3651
3652
GET_VARIANT_PTR(counter, 0);
3653
GET_VARIANT_PTR(container, 1);
3654
3655
const Array *array = VariantInternal::get_array((const Variant *)container);
3656
int64_t *idx = VariantInternal::get_int(counter);
3657
(*idx)++;
3658
3659
if (*idx >= array->size()) {
3660
int jumpto = _code_ptr[ip + 4];
3661
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3662
ip = jumpto;
3663
} else {
3664
GET_VARIANT_PTR(iterator, 2);
3665
*iterator = array->get(*idx);
3666
3667
ip += 5; // Loop again.
3668
}
3669
}
3670
DISPATCH_OPCODE;
3671
3672
#define OPCODE_ITERATE_PACKED_ARRAY(m_var_type, m_elem_type, m_get_func, m_ret_get_func) \
3673
OPCODE(OPCODE_ITERATE_PACKED_##m_var_type##_ARRAY) { \
3674
CHECK_SPACE(4); \
3675
GET_VARIANT_PTR(counter, 0); \
3676
GET_VARIANT_PTR(container, 1); \
3677
const Vector<m_elem_type> *array = VariantInternal::m_get_func((const Variant *)container); \
3678
int64_t *idx = VariantInternal::get_int(counter); \
3679
(*idx)++; \
3680
if (*idx >= array->size()) { \
3681
int jumpto = _code_ptr[ip + 4]; \
3682
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size); \
3683
ip = jumpto; \
3684
} else { \
3685
GET_VARIANT_PTR(iterator, 2); \
3686
*VariantInternal::m_ret_get_func(iterator) = array->get(*idx); \
3687
ip += 5; \
3688
} \
3689
} \
3690
DISPATCH_OPCODE
3691
3692
OPCODE_ITERATE_PACKED_ARRAY(BYTE, uint8_t, get_byte_array, get_int);
3693
OPCODE_ITERATE_PACKED_ARRAY(INT32, int32_t, get_int32_array, get_int);
3694
OPCODE_ITERATE_PACKED_ARRAY(INT64, int64_t, get_int64_array, get_int);
3695
OPCODE_ITERATE_PACKED_ARRAY(FLOAT32, float, get_float32_array, get_float);
3696
OPCODE_ITERATE_PACKED_ARRAY(FLOAT64, double, get_float64_array, get_float);
3697
OPCODE_ITERATE_PACKED_ARRAY(STRING, String, get_string_array, get_string);
3698
OPCODE_ITERATE_PACKED_ARRAY(VECTOR2, Vector2, get_vector2_array, get_vector2);
3699
OPCODE_ITERATE_PACKED_ARRAY(VECTOR3, Vector3, get_vector3_array, get_vector3);
3700
OPCODE_ITERATE_PACKED_ARRAY(COLOR, Color, get_color_array, get_color);
3701
OPCODE_ITERATE_PACKED_ARRAY(VECTOR4, Vector4, get_vector4_array, get_vector4);
3702
3703
OPCODE(OPCODE_ITERATE_OBJECT) {
3704
CHECK_SPACE(4);
3705
3706
GET_VARIANT_PTR(counter, 0);
3707
GET_VARIANT_PTR(container, 1);
3708
3709
#ifdef DEBUG_ENABLED
3710
bool freed = false;
3711
Object *obj = container->get_validated_object_with_check(freed);
3712
if (freed) {
3713
err_text = "Trying to iterate on a previously freed object.";
3714
OPCODE_BREAK;
3715
} else if (!obj) {
3716
err_text = "Trying to iterate on a null value.";
3717
OPCODE_BREAK;
3718
}
3719
#else
3720
Object *obj = *VariantInternal::get_object(container);
3721
#endif
3722
3723
Array ref = { *counter };
3724
Variant vref;
3725
VariantInternal::initialize(&vref, Variant::ARRAY);
3726
*VariantInternal::get_array(&vref) = ref;
3727
3728
const Variant *args[] = { &vref };
3729
3730
Callable::CallError ce;
3731
Variant has_next = obj->callp(CoreStringName(_iter_next), args, 1, ce);
3732
3733
#ifdef DEBUG_ENABLED
3734
if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) {
3735
err_text = vformat(R"(There was an error calling "_iter_next" on iterator object of type %s.)", *container);
3736
OPCODE_BREAK;
3737
}
3738
#endif
3739
if (!has_next.booleanize()) {
3740
int jumpto = _code_ptr[ip + 4];
3741
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3742
ip = jumpto;
3743
} else {
3744
*counter = ref[0];
3745
3746
GET_VARIANT_PTR(iterator, 2);
3747
*iterator = obj->callp(CoreStringName(_iter_get), (const Variant **)&counter, 1, ce);
3748
#ifdef DEBUG_ENABLED
3749
if (ce.error != Callable::CallError::CALL_OK) {
3750
err_text = vformat(R"(There was an error calling "_iter_get" on iterator object of type %s.)", *container);
3751
OPCODE_BREAK;
3752
}
3753
#endif
3754
3755
ip += 5; // Loop again.
3756
}
3757
}
3758
DISPATCH_OPCODE;
3759
3760
OPCODE(OPCODE_ITERATE_RANGE) {
3761
CHECK_SPACE(5);
3762
3763
GET_VARIANT_PTR(counter, 0);
3764
GET_VARIANT_PTR(to_ptr, 1);
3765
GET_VARIANT_PTR(step_ptr, 2);
3766
3767
int64_t to = *VariantInternal::get_int(to_ptr);
3768
int64_t step = *VariantInternal::get_int(step_ptr);
3769
3770
int64_t *count = VariantInternal::get_int(counter);
3771
3772
*count += step;
3773
3774
if ((step < 0 && *count <= to) || (step > 0 && *count >= to)) {
3775
int jumpto = _code_ptr[ip + 5];
3776
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3777
ip = jumpto;
3778
} else {
3779
GET_VARIANT_PTR(iterator, 3);
3780
*VariantInternal::get_int(iterator) = *count;
3781
3782
ip += 6; // Loop again.
3783
}
3784
}
3785
DISPATCH_OPCODE;
3786
3787
OPCODE(OPCODE_STORE_GLOBAL) {
3788
CHECK_SPACE(3);
3789
int global_idx = _code_ptr[ip + 2];
3790
GD_ERR_BREAK(global_idx < 0 || global_idx >= GDScriptLanguage::get_singleton()->get_global_array_size());
3791
3792
GET_VARIANT_PTR(dst, 0);
3793
*dst = GDScriptLanguage::get_singleton()->get_global_array()[global_idx];
3794
3795
ip += 3;
3796
}
3797
DISPATCH_OPCODE;
3798
3799
OPCODE(OPCODE_STORE_NAMED_GLOBAL) {
3800
CHECK_SPACE(3);
3801
int globalname_idx = _code_ptr[ip + 2];
3802
GD_ERR_BREAK(globalname_idx < 0 || globalname_idx >= _global_names_count);
3803
const StringName *globalname = &_global_names_ptr[globalname_idx];
3804
GD_ERR_BREAK(!GDScriptLanguage::get_singleton()->get_named_globals_map().has(*globalname));
3805
3806
GET_VARIANT_PTR(dst, 0);
3807
*dst = GDScriptLanguage::get_singleton()->get_named_globals_map()[*globalname];
3808
3809
ip += 3;
3810
}
3811
DISPATCH_OPCODE;
3812
3813
#define OPCODE_TYPE_ADJUST(m_v_type, m_c_type) \
3814
OPCODE(OPCODE_TYPE_ADJUST_##m_v_type) { \
3815
CHECK_SPACE(2); \
3816
GET_VARIANT_PTR(arg, 0); \
3817
VariantTypeAdjust<m_c_type>::adjust(arg); \
3818
ip += 2; \
3819
} \
3820
DISPATCH_OPCODE
3821
3822
OPCODE_TYPE_ADJUST(BOOL, bool);
3823
OPCODE_TYPE_ADJUST(INT, int64_t);
3824
OPCODE_TYPE_ADJUST(FLOAT, double);
3825
OPCODE_TYPE_ADJUST(STRING, String);
3826
OPCODE_TYPE_ADJUST(VECTOR2, Vector2);
3827
OPCODE_TYPE_ADJUST(VECTOR2I, Vector2i);
3828
OPCODE_TYPE_ADJUST(RECT2, Rect2);
3829
OPCODE_TYPE_ADJUST(RECT2I, Rect2i);
3830
OPCODE_TYPE_ADJUST(VECTOR3, Vector3);
3831
OPCODE_TYPE_ADJUST(VECTOR3I, Vector3i);
3832
OPCODE_TYPE_ADJUST(TRANSFORM2D, Transform2D);
3833
OPCODE_TYPE_ADJUST(VECTOR4, Vector4);
3834
OPCODE_TYPE_ADJUST(VECTOR4I, Vector4i);
3835
OPCODE_TYPE_ADJUST(PLANE, Plane);
3836
OPCODE_TYPE_ADJUST(QUATERNION, Quaternion);
3837
OPCODE_TYPE_ADJUST(AABB, AABB);
3838
OPCODE_TYPE_ADJUST(BASIS, Basis);
3839
OPCODE_TYPE_ADJUST(TRANSFORM3D, Transform3D);
3840
OPCODE_TYPE_ADJUST(PROJECTION, Projection);
3841
OPCODE_TYPE_ADJUST(COLOR, Color);
3842
OPCODE_TYPE_ADJUST(STRING_NAME, StringName);
3843
OPCODE_TYPE_ADJUST(NODE_PATH, NodePath);
3844
OPCODE_TYPE_ADJUST(RID, RID);
3845
OPCODE_TYPE_ADJUST(OBJECT, Object *);
3846
OPCODE_TYPE_ADJUST(CALLABLE, Callable);
3847
OPCODE_TYPE_ADJUST(SIGNAL, Signal);
3848
OPCODE_TYPE_ADJUST(DICTIONARY, Dictionary);
3849
OPCODE_TYPE_ADJUST(ARRAY, Array);
3850
OPCODE_TYPE_ADJUST(PACKED_BYTE_ARRAY, PackedByteArray);
3851
OPCODE_TYPE_ADJUST(PACKED_INT32_ARRAY, PackedInt32Array);
3852
OPCODE_TYPE_ADJUST(PACKED_INT64_ARRAY, PackedInt64Array);
3853
OPCODE_TYPE_ADJUST(PACKED_FLOAT32_ARRAY, PackedFloat32Array);
3854
OPCODE_TYPE_ADJUST(PACKED_FLOAT64_ARRAY, PackedFloat64Array);
3855
OPCODE_TYPE_ADJUST(PACKED_STRING_ARRAY, PackedStringArray);
3856
OPCODE_TYPE_ADJUST(PACKED_VECTOR2_ARRAY, PackedVector2Array);
3857
OPCODE_TYPE_ADJUST(PACKED_VECTOR3_ARRAY, PackedVector3Array);
3858
OPCODE_TYPE_ADJUST(PACKED_COLOR_ARRAY, PackedColorArray);
3859
OPCODE_TYPE_ADJUST(PACKED_VECTOR4_ARRAY, PackedVector4Array);
3860
3861
OPCODE(OPCODE_ASSERT) {
3862
CHECK_SPACE(3);
3863
3864
#ifdef DEBUG_ENABLED
3865
GET_VARIANT_PTR(test, 0);
3866
bool result = test->booleanize();
3867
3868
if (!result) {
3869
String message_str;
3870
if (_code_ptr[ip + 2] != 0) {
3871
GET_VARIANT_PTR(message, 1);
3872
Variant message_var = *message;
3873
if (message->get_type() != Variant::NIL) {
3874
message_str = message_var;
3875
}
3876
}
3877
if (message_str.is_empty()) {
3878
err_text = "Assertion failed.";
3879
} else {
3880
err_text = "Assertion failed: " + message_str;
3881
}
3882
OPCODE_BREAK;
3883
}
3884
3885
#endif
3886
ip += 3;
3887
}
3888
DISPATCH_OPCODE;
3889
3890
OPCODE(OPCODE_BREAKPOINT) {
3891
#ifdef DEBUG_ENABLED
3892
if (EngineDebugger::is_active()) {
3893
GDScriptLanguage::get_singleton()->debug_break("Breakpoint Statement", true);
3894
}
3895
#endif
3896
ip += 1;
3897
}
3898
DISPATCH_OPCODE;
3899
3900
OPCODE(OPCODE_LINE) {
3901
CHECK_SPACE(2);
3902
3903
line = _code_ptr[ip + 1];
3904
ip += 2;
3905
3906
if (EngineDebugger::is_active()) {
3907
// line
3908
bool do_break = false;
3909
3910
if (unlikely(EngineDebugger::get_script_debugger()->get_lines_left() > 0)) {
3911
if (EngineDebugger::get_script_debugger()->get_depth() <= 0) {
3912
EngineDebugger::get_script_debugger()->set_lines_left(EngineDebugger::get_script_debugger()->get_lines_left() - 1);
3913
}
3914
if (EngineDebugger::get_script_debugger()->get_lines_left() <= 0) {
3915
do_break = true;
3916
}
3917
}
3918
3919
if (EngineDebugger::get_script_debugger()->is_breakpoint(line, source)) {
3920
do_break = true;
3921
}
3922
3923
if (unlikely(do_break)) {
3924
GDScriptLanguage::get_singleton()->debug_break("Breakpoint", true);
3925
}
3926
3927
EngineDebugger::get_singleton()->line_poll();
3928
}
3929
}
3930
DISPATCH_OPCODE;
3931
3932
OPCODE(OPCODE_END) {
3933
#ifdef DEBUG_ENABLED
3934
exit_ok = true;
3935
#endif
3936
OPCODE_BREAK;
3937
}
3938
3939
#if 0 // Enable for debugging.
3940
default: {
3941
err_text = "Illegal opcode " + itos(_code_ptr[ip]) + " at address " + itos(ip);
3942
OPCODE_BREAK;
3943
}
3944
#endif
3945
}
3946
3947
OPCODES_END
3948
#ifdef DEBUG_ENABLED
3949
if (exit_ok) {
3950
OPCODE_OUT;
3951
}
3952
//error
3953
// function, file, line, error, explanation
3954
String err_file;
3955
bool instance_valid_with_script = p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid();
3956
if (instance_valid_with_script && !get_script()->path.is_empty()) {
3957
err_file = get_script()->path;
3958
} else if (script) {
3959
err_file = script->path;
3960
}
3961
if (err_file.is_empty()) {
3962
err_file = "<built-in>";
3963
}
3964
String err_func = name;
3965
if (instance_valid_with_script && p_instance->script->local_name != StringName()) {
3966
err_func = p_instance->script->local_name.operator String() + "." + err_func;
3967
}
3968
int err_line = line;
3969
if (err_text.is_empty()) {
3970
err_text = "Internal script error! Opcode: " + itos(last_opcode) + " (please report).";
3971
}
3972
3973
_err_print_error(err_func.utf8().get_data(), err_file.utf8().get_data(), err_line, err_text.utf8().get_data(), false, ERR_HANDLER_SCRIPT);
3974
GDScriptLanguage::get_singleton()->debug_break(err_text, false);
3975
3976
// Get a default return type in case of failure
3977
retvalue = _get_default_variant_for_data_type(return_type);
3978
#endif
3979
3980
OPCODE_OUT;
3981
}
3982
3983
OPCODES_OUT
3984
#ifdef DEBUG_ENABLED
3985
if (GDScriptLanguage::get_singleton()->profiling) {
3986
uint64_t time_taken = OS::get_singleton()->get_ticks_usec() - function_start_time;
3987
profile.total_time.add(time_taken);
3988
profile.self_time.add(time_taken - function_call_time);
3989
profile.frame_total_time.add(time_taken);
3990
profile.frame_self_time.add(time_taken - function_call_time);
3991
if (Thread::get_caller_id() == Thread::get_main_id()) {
3992
GDScriptLanguage::get_singleton()->script_frame_time += time_taken - function_call_time;
3993
}
3994
}
3995
#endif
3996
3997
// Check if this is not the last time it was interrupted by `await` or if it's the first time executing.
3998
// If that is the case then we exit the function as normal. Otherwise we postpone it until the last `await` is completed.
3999
// This ensures the call stack can be properly shown when using `await`, showing what resumed the function.
4000
if (!p_state || awaited) {
4001
GDScriptLanguage::get_singleton()->exit_function();
4002
4003
// Free stack, except reserved addresses.
4004
for (int i = FIXED_ADDRESSES_MAX; i < _stack_size; i++) {
4005
stack[i].~Variant();
4006
}
4007
}
4008
4009
// Always free reserved addresses, since they are never copied.
4010
for (int i = 0; i < FIXED_ADDRESSES_MAX; i++) {
4011
stack[i].~Variant();
4012
}
4013
4014
call_depth--;
4015
4016
if (p_state && !awaited) {
4017
// This means we have finished executing a resumed function and it was not awaited again.
4018
4019
// Signal the next function-state to resume.
4020
const Variant *args[1] = { &retvalue };
4021
p_state->completed.emit(args, 1);
4022
4023
// Exit function only after executing the remaining function states to preserve async call stack.
4024
GDScriptLanguage::get_singleton()->exit_function();
4025
}
4026
4027
return retvalue;
4028
}
4029
4030