Как современные VMs обрабатывают выделение памяти?

Я работаю над простой машиной стека, написанной на C, в основном для учебных целей. После использования malloc/free для моих операций с памятью я подумал, что было бы неплохо прочитать определенный код выделения памяти из современных виртуальных машин.

Я загрузил исходный код Lua и начал его читать. Через некоторое время я понял, что есть много макросов, и я не мог найти код, в котором выполняется реальное распределение памяти (т. е. malloc призывать.)

find . -exec grep -i "malloc" '{}' ; -print

он напечатал только некоторые макросы Lua, которые имеют malloc слово в своих названиях. Lua VM (и язык программирования) не использует malloc на всех!

Итак, это приводит меня к вопросу: как современные VMs обрабатывают выделение памяти? Как Lua выделяет память из кучи? Есть ли какие-либо способы выделения, кроме malloc? Какие плюсы/минусы других методов?

мне также интересно о лучших практиках, шаблонах дизайна и т. д. для безопасного работа над выделенной памятью. Я вижу в источнике Lua, что перед выделением памяти существует много косвенных действий. Где я могу узнать об этом?

2 ответов


Lua определенно использует malloc, в виде realloc (можно также передать пользовательский распределитель), однако, поскольку Lua использует GC как 99% языков на основе VM, он использует макросы для автоматического добавления блока заголовка GC к распределению.

вы найдете память Луа все обрабатывается LuaM_ подпрограммы lmem.c и lmem.h, все они используют глобальное состояние виртуальной машины для хранения распределителя, который изначально установлен в l_alloc (от lauxlib.c), но может быть изменен by lua_setallocf.

недавно LuaJIT добавил выделение тонет и планирует некоторые действительно интересные функции памяти, которые вы можете прочитать в этой статье на LuaJIT Сбор Мусора. В статье рассматривается много стратегии и дизайна, вращающихся вокруг выделения памяти VM/JIT, погружения, агрегации и сбора мусора.

как вы можете видеть, стратегии выделения памяти и потопления очень тесно связаны с GC, который использует (если таковые имеются).

In термины pro и con различной памяти распределители, используя стандартный malloc прост в использовании, но за счет скорости и потерь на выравнивание и различных дополнительных блоков, помеченных на каждом распределении.

переход к более продвинутым распределителям arena, pool, slab и block, мы можем значительно ускорить процесс (особенно для внутренних распределений VM фиксированного размера) и избежать фрагментации и накладных расходов, которые могут возникнуть с более общими распределителями, такими как malloc, но, конечно, эти распределители более сложны, и вы должны отлаживать их, если вы начинаете с нуля (что в большей системе, такой как виртуальная машина, просто просит проблем), как и в проверенной CRT malloc реализация.


ядро Lua не использует malloc и друзей. Он полагается на пользовательскую функцию выделения памяти, которая имеет reallocсемантику (а точне при лечении NULL указатели и размеры 0). См.lua_Alloc.

вспомогательная библиотека Lua обеспечивает удобство luaL_newstate функция, которая создает состояние Lua через core