Skip to content

Commit e2b6d92

Browse files
committed
Speed up lambda capture handling
Updated GDScriptLambdaCallable::call and GDScriptLambdaSelfCallable::call to use alloca instead of Vector when using captures, to avoid extra allocation/copy_on_write calls on each lambda function call.
1 parent 6681f25 commit e2b6d92

File tree

1 file changed

+12
-12
lines changed

1 file changed

+12
-12
lines changed

modules/gdscript/gdscript_lambda_callable.cpp

+12-12
Original file line numberDiff line numberDiff line change
@@ -97,25 +97,25 @@ void GDScriptLambdaCallable::call(const Variant **p_arguments, int p_argcount, V
9797
}
9898

9999
if (captures_amount > 0) {
100-
Vector<const Variant *> args;
101-
args.resize(p_argcount + captures_amount);
100+
const int total_argcount = p_argcount + captures_amount;
101+
const Variant **args = (const Variant **)alloca(sizeof(Variant *) * total_argcount);
102102
for (int i = 0; i < captures_amount; i++) {
103-
args.write[i] = &captures[i];
103+
args[i] = &captures[i];
104104
if (captures[i].get_type() == Variant::OBJECT) {
105105
bool was_freed = false;
106106
captures[i].get_validated_object_with_check(was_freed);
107107
if (was_freed) {
108108
ERR_PRINT(vformat(R"(Lambda capture at index %d was freed. Passed "null" instead.)", i));
109109
static Variant nil;
110-
args.write[i] = &nil;
110+
args[i] = &nil;
111111
}
112112
}
113113
}
114114
for (int i = 0; i < p_argcount; i++) {
115-
args.write[i + captures_amount] = p_arguments[i];
115+
args[i + captures_amount] = p_arguments[i];
116116
}
117117

118-
r_return_value = function->call(nullptr, args.ptrw(), args.size(), r_call_error);
118+
r_return_value = function->call(nullptr, args, total_argcount, r_call_error);
119119
switch (r_call_error.error) {
120120
case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT:
121121
r_call_error.argument -= captures_amount;
@@ -229,25 +229,25 @@ void GDScriptLambdaSelfCallable::call(const Variant **p_arguments, int p_argcoun
229229
}
230230

231231
if (captures_amount > 0) {
232-
Vector<const Variant *> args;
233-
args.resize(p_argcount + captures_amount);
232+
const int total_argcount = p_argcount + captures_amount;
233+
const Variant **args = (const Variant **)alloca(sizeof(Variant *) * total_argcount);
234234
for (int i = 0; i < captures_amount; i++) {
235-
args.write[i] = &captures[i];
235+
args[i] = &captures[i];
236236
if (captures[i].get_type() == Variant::OBJECT) {
237237
bool was_freed = false;
238238
captures[i].get_validated_object_with_check(was_freed);
239239
if (was_freed) {
240240
ERR_PRINT(vformat(R"(Lambda capture at index %d was freed. Passed "null" instead.)", i));
241241
static Variant nil;
242-
args.write[i] = &nil;
242+
args[i] = &nil;
243243
}
244244
}
245245
}
246246
for (int i = 0; i < p_argcount; i++) {
247-
args.write[i + captures_amount] = p_arguments[i];
247+
args[i + captures_amount] = p_arguments[i];
248248
}
249249

250-
r_return_value = function->call(static_cast<GDScriptInstance *>(object->get_script_instance()), args.ptrw(), args.size(), r_call_error);
250+
r_return_value = function->call(static_cast<GDScriptInstance *>(object->get_script_instance()), args, total_argcount, r_call_error);
251251
switch (r_call_error.error) {
252252
case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT:
253253
r_call_error.argument -= captures_amount;

0 commit comments

Comments
 (0)