Очевидно, GoLang по-прежнему использует неэффективное соглашение о вызовах, в котором единственными сохраняемыми вызовами (или энергонезависимыми) регистрами являются RSP и RBP.
Вызов runtime.gosave
выглядит компилятору, как и любой другой вызов функции (т. е. он в конечном итоге возвращается после выполнения каких-либо действий и не изменяет ничего выше своего собственного стекового фрейма). Как и при любом другом вызове функции, вызывающая сторона должна исходить из того, что она уничтожает все регистры с изменяющимся вызовом (энергозависимые) (все, кроме RSP и RBP). Таким образом, любые значения, которые он хочет пережить при вызове, должны быть перенаправлены в слоты стека (или в другую область памяти, к которой они принадлежат).
По той же причине C setjmp
должен сохранять только вызов. сохраненные регистры. А функции переключения контекста в ядре одинаковы.
В этом посте , посвященном Google * 2017, *1013* говорится, что так работает соглашение о вызовах / ABI, и из связанного кода оно выглядит так же не было улучшено.
Go соглашение о вызовах также неэффективно передает все аргументы в стеке, в отличие от x86-64 System V ABI, который передает первые 6 целочисленных аргументов (и первые 8 FP) в регистры.