Начальная загрузка — это процесс запуска функций системы, подготавливающий возможность исполнения кода на Ruby. Она проходит семь стадий:
VM: виртуальная машина способна загружать и выполнять байткод, посылать сообщения (то есть, находить и вызывать методы); все примитивные функции уже доступны, но еще не видны как методы Ruby.
Класс Class
на этой ранней стадии должен быть явно задан путем объявления
самого себя своим классом, а своим суперклассом — Module
. В дополнение
к Class
и Module
здесь же создаются еще несколько базовых классов,
включая Object
, Tuple
, LookupTable
и MethodTable
.
Теперь, когда уже можно определять классы, получают приказ начать
самоинициализацию еще около 35 встроенных классов; создаются символы для
методов высшего уровня :object_id
, :call
, protected
и т.п.;
определяются базовые исключения (exceptions) и регистрируются примитивы.
В этот момент уже определено поведение, достаточное для того, чтобы начать загружать остальное runtime-ядро, целиком написанное на Ruby. Это, в свою очередь, также делается в несколько проходов по мере «роста» языка.
Альфа: начало загрузки кода на Ruby. Уже есть возможность открывать
классы и модули и определять методы. В kernel/alpha.rb
реализованы
минимальные средства для поддержки следующих методов:
attr_reader :sym
attr_writer :sym
attr_accessor :sym
private :sym
protected :sym
module_function :sym
include mod
Помимо этого код имеет возможность инициировать исключения и прекращать выполнение процесса. Эта стадия закладывает основание для следующих двух.
Бутстрап: продолжается добавление минимального функционала для поддержки загружающихся «платформы» и «основы» (“platform” и “common”, см. ниже). Функции-примитивы добавляются в большинство классов ядра.
Платформа: запускается FFI (интерфейс внешних функций) и создаются интерфейсные методы платформо-специфических функций. Как только все это настроено, к системе подключаются платформо-специфические детали вроде указателей, файловых операций, арифметики и вызовов POSIX.
Основа: создается подавляющее большинство классов Основной (core
)
библиотеки. Основные классы Ruby построены настолько независимо от
конкретной реализации, насколько это возможно. На этом же этапе добавляется
бóльшая часть функциональных возможностей Rubinius-специфических
классов.
Дельта: добавляются финальные версии методов из ряда #attr_reader
и
т.п. Кроме этого, подключаются зависимые от реализации версии методов
Основы.
Загрузчик: выполняется скомпилированная версия kernel/loader.rb
.
Конечная стадия загрузки настраивает жизненный цикл Ruby-процесса. Она начинается с присоединения виртуальной машины к системе, затем настраиваются пути загрузки, читаются скрипты индивидуальной настройки из домашней директории. На этом этапе улавливаются сигналы и обрабатываются аргументы командной строки.
После всего либо запускается переданный в командной строке скрипт, либо
стартует интерактивная оболочка Ruby. Когда и они заканчивают работу,
отрабатываются все зарегистрированные блоки at_exit
, финализируются все
объекты и процесс прекращается.
Ряд описанных стадий загрузки реализован в файлах, находящихся в
соответствующих директориях ядра: bootstrap
, platform
, common
, и
delta
. Порядок загрузки этих директорий определен в runtime/index
.
Код уровня скрипта, тела класса или модуля выполняется после загрузки rbc-файла. К примеру, при загрузке фрагмента
class SomeClass
attr_accessor :value
end
выполняется вызов #attr_accessor
. Для этого требуется, чтобы до файла,
содержащего некий код, было загружено все, что вызывается из содержащихся в
нем описаний скриптов, классов и модулей. kernel/alpha.rb
содержит
бóльшую часть определений, необходимых на уровне скрипта или модуля.
Вместе с тем, между некоторыми файлами платформы, основы, дельты и компилятора
существуют и иные зависимости, влияющие на порядок загрузки.
Эти зависимости прописаны в файлах load_order.txt
, находящихся в каждой из
директорий kernel/**
. Если Вы модифицируете код, добавляющий порядковую
зависимость, Вам следует отредактировать соответствующий load_order.txt
,
поместив файл, который зависит, после того, от которого он зависит. Если Вы
добавляете новый файл в одну из директорий ядра, Вы должны добавить его имя в
load_order.txt
его директории. При сборке эти файлы копируются в
соответствующие директории runtime/**
. Во время каждой из вышеописанных
стадий запуска виртуальная машина загружает файлы в порядке их перечисления в
load_order.txt
.