Судя по всему, GoLang по-прежнему использует неэффективное соглашение о вызовах, при котором единственными сохраняемыми вызовами (т. е. энергонезависимыми) регистрами являются RSP и RBP.
Вызов runtime.gosave
выглядит для компилятора как любой другой вызов функции (т. е. он в конечном итоге возвращается после выполнения некоторых действий и не изменяет ничего выше своего собственного фрейма стека). Как и любой другой вызов функции, вызывающая сторона должна предполагать, что он уничтожает все затираемые вызовом (изменчивые) регистры (все, кроме RSP и RBP). Таким образом, любые значения, которые он хочет сохранить после вызова, должны быть перенесены в слоты стека (или в другую область памяти, где они принадлежат).
По той же причине C setjmp
должен сохранять только регистры, сохраняемые вызовом. И функции переключения контекста ядра такие же.
В этом сообщении о группах Google от 2017 года говорится, что так оно и есть. соглашение / ABI работает, и из связанного кода похоже, что он до сих пор не улучшен.
Соглашение о вызовах Go также неэффективно передает все аргументы в стеке, в отличие от x86-64 System V ABI, который передает первые 6 целочисленных аргументов (и первые 8 FP) в регистрах.
person
Peter Cordes
schedule
11.02.2020
runtime.gosave
уничтожит все остальные регистры, заставив вызывающую сторону сохранить их в этом случае. Я не использую go, поэтому не могу легко проверить; надеюсь, кто-то, кто знает ABI и дизайн Go, сможет легче ответить на ваш вопрос. - person Peter Cordes   schedule 11.02.2020Well, sort of. In the current ports there are no callee-saved registers other than the frame pointer.
groups.google.com/forum/m/ #!topic/golang-dev/HDLMMYQv7Ak - person Lime   schedule 11.02.2020