@@ -437,31 +437,22 @@ class GDScriptLanguage : public ScriptLanguage {
437437 GDScriptInstance *instance = nullptr ;
438438 int *ip = nullptr ;
439439 int *line = nullptr ;
440+ CallLevel *prev = nullptr ; // Reverse linked list (stack).
440441 };
441442
442443 static thread_local int _debug_parse_err_line;
443444 static thread_local String _debug_parse_err_file;
444445 static thread_local String _debug_error;
445- struct CallStack {
446- CallLevel *levels = nullptr ;
447- int stack_pos = 0 ;
448-
449- void free () {
450- if (levels) {
451- memdelete_arr (levels);
452- levels = nullptr ;
453- }
454- }
455- ~CallStack () {
456- free ();
457- }
458- };
459446
460- static thread_local CallStack _call_stack;
461- int _debug_max_call_stack = 0 ;
447+ static thread_local CallLevel *_call_stack;
448+ static thread_local uint32_t _call_stack_size;
449+ uint32_t _debug_max_call_stack = 0 ;
450+
462451 bool track_call_stack = false ;
463452 bool track_locals = false ;
464453
454+ static CallLevel *_get_stack_level (uint32_t p_level);
455+
465456 void _add_global (const StringName &p_name, const Variant &p_value);
466457 void _remove_global (const StringName &p_name);
467458
@@ -492,23 +483,20 @@ class GDScriptLanguage : public ScriptLanguage {
492483 bool debug_break (const String &p_error, bool p_allow_continue = true );
493484 bool debug_break_parse (const String &p_file, int p_line, const String &p_error);
494485
495- _FORCE_INLINE_ void enter_function (GDScriptInstance *p_instance, GDScriptFunction *p_function, Variant *p_stack, int *p_ip, int *p_line) {
486+ _FORCE_INLINE_ void enter_function (CallLevel *call_level, GDScriptInstance *p_instance, GDScriptFunction *p_function, Variant *p_stack, int *p_ip, int *p_line) {
496487 if (!track_call_stack) {
497488 return ;
498489 }
499490
500- if (unlikely (_call_stack.levels == nullptr )) {
501- _call_stack.levels = memnew_arr (CallLevel, _debug_max_call_stack + 1 );
502- }
503-
504491#ifdef DEBUG_ENABLED
505492 ScriptDebugger *script_debugger = EngineDebugger::get_script_debugger ();
506493 if (script_debugger != nullptr && script_debugger->get_lines_left () > 0 && script_debugger->get_depth () >= 0 ) {
507494 script_debugger->set_depth (script_debugger->get_depth () + 1 );
508495 }
509496#endif
510497
511- if (unlikely (_call_stack.stack_pos >= _debug_max_call_stack)) {
498+ if (unlikely (_call_stack_size >= _debug_max_call_stack)) {
499+ // stack overflow
512500 _debug_error = vformat (" Stack overflow (stack size: %s). Check for infinite recursion in your script." , _debug_max_call_stack);
513501
514502#ifdef DEBUG_ENABLED
@@ -520,13 +508,14 @@ class GDScriptLanguage : public ScriptLanguage {
520508 return ;
521509 }
522510
523- CallLevel &call_level = _call_stack.levels [_call_stack.stack_pos ];
524- call_level.stack = p_stack;
525- call_level.instance = p_instance;
526- call_level.function = p_function;
527- call_level.ip = p_ip;
528- call_level.line = p_line;
529- _call_stack.stack_pos ++;
511+ call_level->prev = _call_stack;
512+ _call_stack = call_level;
513+ call_level->stack = p_stack;
514+ call_level->instance = p_instance;
515+ call_level->function = p_function;
516+ call_level->ip = p_ip;
517+ call_level->line = p_line;
518+ _call_stack_size++;
530519 }
531520
532521 _FORCE_INLINE_ void exit_function () {
@@ -536,35 +525,42 @@ class GDScriptLanguage : public ScriptLanguage {
536525
537526#ifdef DEBUG_ENABLED
538527 ScriptDebugger *script_debugger = EngineDebugger::get_script_debugger ();
539- if (script_debugger != nullptr && script_debugger->get_lines_left () > 0 && script_debugger->get_depth () >= 0 ) {
528+ if (script_debugger && script_debugger->get_lines_left () > 0 && script_debugger->get_depth () >= 0 ) {
540529 script_debugger->set_depth (script_debugger->get_depth () - 1 );
541530 }
542531#endif
543532
544- if (unlikely (_call_stack.stack_pos == 0 )) {
545- _debug_error = " Stack Underflow (Engine Bug)" ;
546-
533+ if (unlikely (_call_stack_size == 0 )) {
547534#ifdef DEBUG_ENABLED
548- if (script_debugger != nullptr ) {
535+ if (script_debugger) {
536+ _debug_error = " Stack Underflow (Engine Bug)" ;
549537 script_debugger->debug (this );
538+ } else {
539+ ERR_PRINT (" Stack underflow! (Engine Bug)" );
550540 }
541+ #else // !DEBUG_ENABLED
542+ ERR_PRINT (" Stack underflow! (Engine Bug)" );
551543#endif
552-
553544 return ;
554545 }
555546
556- _call_stack.stack_pos --;
547+ _call_stack_size--;
548+ _call_stack = _call_stack->prev ;
557549 }
558550
559551 virtual Vector<StackInfo> debug_get_current_stack_info () override {
560552 Vector<StackInfo> csi;
561- csi.resize (_call_stack.stack_pos );
562- for (int i = 0 ; i < _call_stack.stack_pos ; i++) {
563- csi.write [_call_stack.stack_pos - i - 1 ].line = _call_stack.levels [i].line ? *_call_stack.levels [i].line : 0 ;
564- if (_call_stack.levels [i].function ) {
565- csi.write [_call_stack.stack_pos - i - 1 ].func = _call_stack.levels [i].function ->get_name ();
566- csi.write [_call_stack.stack_pos - i - 1 ].file = _call_stack.levels [i].function ->get_script ()->get_script_path ();
553+ csi.resize (_call_stack_size);
554+ CallLevel *cl = _call_stack;
555+ uint32_t idx = 0 ;
556+ while (cl) {
557+ csi.write [idx].line = *cl->line ;
558+ if (cl->function ) {
559+ csi.write [idx].func = cl->function ->get_name ();
560+ csi.write [idx].file = cl->function ->get_script ()->get_script_path ();
567561 }
562+ idx++;
563+ cl = cl->prev ;
568564 }
569565 return csi;
570566 }
0 commit comments