Почему Golang сохраняет только% rsp,% rip и% rbp (без других регистров, сохраненных вызываемыми) при переключении контекста? - PullRequest
1 голос
/ 11 февраля 2020

В общих реализациях переключения контекста потока пользователя (например, setjmp/longjmp и способ function return) мы сохраняем и восстанавливаем регистры, сохраненные вызываемым пользователем, но golang только сохраняют и восстанавливают %rsp, %rip и %rbp в gobuf .

В качестве примера рассмотрим x86_64, golang сохраните контекст программы с помощью runtime.gosave и восстановите контекст программы с помощью runtime. gogo.

Так почему golang делает это таким образом?

1 Ответ

1 голос
/ 11 февраля 2020

Очевидно, GoLang по-прежнему использует неэффективное соглашение о вызовах, в котором единственными сохраняемыми вызовами (или энергонезависимыми) регистрами являются RSP и RBP.

Вызов runtime.gosave выглядит компилятору, как и любой другой вызов функции (т. е. он в конечном итоге возвращается после выполнения каких-либо действий и не изменяет ничего выше своего собственного стекового фрейма). Как и при любом другом вызове функции, вызывающая сторона должна исходить из того, что она уничтожает все регистры с изменяющимся вызовом (энергозависимые) (все, кроме RSP и RBP). Таким образом, любые значения, которые он хочет пережить при вызове, должны быть перенаправлены в слоты стека (или в другую область памяти, к которой они принадлежат).

По той же причине C setjmp должен сохранять только вызов. сохраненные регистры. А функции переключения контекста в ядре одинаковы.


В этом посте , посвященном Google * 2017, *1013* говорится, что так работает соглашение о вызовах / ABI, и из связанного кода оно выглядит так же не было улучшено.

Go соглашение о вызовах также неэффективно передает все аргументы в стеке, в отличие от x86-64 System V ABI, который передает первые 6 целочисленных аргументов (и первые 8 FP) в регистры.

...