Ермаков И. Е. Внутренний интерфейс модуля Kernel системы BlackBox


Составитель: Ермаков И.Е. Исправления и дополнения: Ильин А.С.

 DEFINITION Kernel;
 
   IMPORT SYSTEM;
 
   CONST
     nameLen = 256;
     littleEndian = TRUE;
     timeResolution = 1000;
     processor = 10;
     objType = "ocf";
     symType = "osf";
     docType = "odc";
 
     done = 0;
     fileNotFound = 1;
     syntaxError = 2;
     objNotFound = 3;
     illegalFPrint = 4;
     cyclicImport = 5;
     noMem = 6;
     commNotFound = 7;
     commSyntaxError = 8;
     moduleNotFound = 9;
 
     TYPE
     Name = ARRAY 256 OF SHORTCHAR;
 
     Command = PROCEDURE;
 
     Module = POINTER TO RECORD [untagged] 
       next-: Module;
       opts-: SET;
       refcnt-: INTEGER;
       compTime-, loadTime-: ARRAY 6 OF SHORTINT;
       ext-: INTEGER;
       term-: Command;
       nofimps-, nofptrs-, csize-, dsize-, rsize-, code-,
 data-, refs-, procBase-, varBase-: INTEGER;
       names-: POINTER TO ARRAY [untagged] OF SHORTCHAR;
       ptrs-: POINTER TO ARRAY [untagged] OF INTEGER;
       imports-: POINTER TO ARRAY [untagged] OF Module;
       export-: Directory;
       name-: Name
     END;
 
     Type = POINTER TO RECORD [untagged] 
       size-: INTEGER;
       mod-: Module;
       id-: INTEGER;
       base-: ARRAY 16 OF Type;
       fields-: Directory;
       ptroffs-: ARRAY 1000000 OF INTEGER
     END;
 
     Object = POINTER TO ObjDesc;
     ObjDesc = RECORD [untagged] 
       fprint-, offs-, id-: INTEGER;
       struct-: Type
     END;
 
     Directory = POINTER TO RECORD [untagged] 
       num-: INTEGER;
       obj-: ARRAY 1000000 OF ObjDesc
     END;
 
     Handler = PROCEDURE;
 
     Reducer = POINTER TO ABSTRACT RECORD 
       (r: Reducer) Reduce (full: BOOLEAN), NEW, ABSTRACT
     END;
 
     TrapCleaner = POINTER TO ABSTRACT RECORD 
       (c: TrapCleaner) Cleanup, NEW, EMPTY
     END;
 
     TryHandler = PROCEDURE (a, b, c: INTEGER);
 
     Identifier = ABSTRACT RECORD 
       typ: INTEGER;
       obj-: ANYPTR;
       (VAR id: Identifier) Identified (): BOOLEAN, NEW, ABSTRACT
     END;
 
     ItemExt = POINTER TO ABSTRACT RECORD 
       (e: ItemExt) BaseTyp (): INTEGER, NEW, ABSTRACT;
       (e: ItemExt) BoolVal (): BOOLEAN, NEW, ABSTRACT;
       (e: ItemExt) Call (OUT ok: BOOLEAN), NEW, ABSTRACT;
       (e: ItemExt) CharVal (): CHAR, NEW, ABSTRACT;
       (e: ItemExt) Deref (VAR ref: ANYREC), NEW, ABSTRACT;
       (e: ItemExt) GetSStringVal (OUT x: ARRAY OF SHORTCHAR;
            OUT ok: BOOLEAN), NEW, ABSTRACT;
       (e: ItemExt) GetStringVal (OUT x: ARRAY OF CHAR;
            OUT ok: BOOLEAN), NEW, ABSTRACT;
       (e: ItemExt) Index (index: INTEGER; VAR elem: ANYREC), NEW, ABSTRACT;
       (e: ItemExt) IntVal (): INTEGER, NEW, ABSTRACT;
       (e: ItemExt) Len (): INTEGER, NEW, ABSTRACT;
       (e: ItemExt) LongVal (): LONGINT, NEW, ABSTRACT;
       (e: ItemExt) Lookup (name: ARRAY OF CHAR; VAR i: ANYREC), NEW, ABSTRACT;
       (e: ItemExt) PtrVal (): ANYPTR, NEW, ABSTRACT;
       (e: ItemExt) PutBoolVal (x: BOOLEAN), NEW, ABSTRACT;
       (e: ItemExt) PutCharVal (x: CHAR), NEW, ABSTRACT;
       (e: ItemExt) PutIntVal (x: INTEGER), NEW, ABSTRACT;
       (e: ItemExt) PutLongVal (x: LONGINT), NEW, ABSTRACT;
       (e: ItemExt) PutPtrVal (x: ANYPTR), NEW, ABSTRACT;
       (e: ItemExt) PutRealVal (x: REAL), NEW, ABSTRACT;
       (e: ItemExt) PutSStringVal (IN x: ARRAY OF SHORTCHAR;
            OUT ok: BOOLEAN), NEW, ABSTRACT;
       (e: ItemExt) PutSetVal (x: SET), NEW, ABSTRACT;
       (e: ItemExt) PutStringVal (IN x: ARRAY OF CHAR;
            OUT ok: BOOLEAN), NEW, ABSTRACT;
       (e: ItemExt) RealVal (): REAL, NEW, ABSTRACT;
       (e: ItemExt) SetVal (): SET, NEW, ABSTRACT;
       (e: ItemExt) Size (): INTEGER, NEW, ABSTRACT;
       (e: ItemExt) Valid (): BOOLEAN, NEW, ABSTRACT
     END;
 
     ItemAttr = RECORD 
       obj, vis, typ, adr: INTEGER;
       mod: Module;
       desc: Type;
       ptr: SYSTEM.PTR;
       ext: ItemExt
     END;
 
     Hook = POINTER TO ABSTRACT RECORD END;
 
     LoaderHook = POINTER TO ABSTRACT RECORD (Kernel.Hook)
       (h: LoaderHook) Info (OUT importing, imported, object: ARRAY OF CHAR),
           NEW, ABSTRACT;
       (h: LoaderHook) Res (): INTEGER, NEW, ABSTRACT;
       (h: LoaderHook) ResDone, NEW, ABSTRACT;
       (h: LoaderHook) ThisMod (IN name: ARRAY OF SHORTCHAR): Kernel.Module,
           NEW, ABSTRACT
     END;
 
   VAR
     modList-: Module;
     trapCount-: INTEGER;
     err-: INTEGER;
     pc-: INTEGER;
     sp-: INTEGER;
     fp-: INTEGER;
     stack-: INTEGER;
     val-: INTEGER;
     comSig-: INTEGER;
     watcher: PROCEDURE (event: INTEGER);
 
   PROCEDURE SplitName (name: ARRAY OF CHAR; VAR head, tail: ARRAY OF CHAR);
   PROCEDURE MakeFileName (VAR name: ARRAY OF CHAR; type: ARRAY OF CHAR);
   PROCEDURE Time (): LONGINT;
   PROCEDURE Beep;
   PROCEDURE LoadDll (IN name: ARRAY OF SHORTCHAR; VAR ok: BOOLEAN);
   PROCEDURE ThisDllObj (mode, fprint: INTEGER; IN dll, name: ARRAY OF SHORTCHAR): INTEGER;
   PROCEDURE GetDllArea (IN name: ARRAY OF SHORTCHAR; OUT beg, size: INTEGER);
 
   PROCEDURE InstallReducer (r: Reducer);
   PROCEDURE InstallTrapViewer (h: Handler);
   PROCEDURE InstallTrapChecker (h: Handler);
   PROCEDURE InstallTrapGlobalChecker (h: Command);
   PROCEDURE RemoveTrapGlobalChecker (h: Command);
   PROCEDURE PushTrapCleaner (c: TrapCleaner);
   PROCEDURE PopTrapCleaner (c: TrapCleaner);
   PROCEDURE InstallCleaner (p: Command);
   PROCEDURE RemoveCleaner (p: Command);
   PROCEDURE Cleanup;
   PROCEDURE Start (code: Command);
   PROCEDURE Quit (exitCode: INTEGER);
   PROCEDURE FatalError (id: INTEGER; str: ARRAY OF CHAR);
   PROCEDURE SetTrapGuard (on: BOOLEAN);
   PROCEDURE Try (h: TryHandler; a, b, c: INTEGER);
   PROCEDURE InterfaceTrapHandler (excpRec, estFrame, context, dispCont: INTEGER): INTEGER;
   PROCEDURE MainBreak;
 
   PROCEDURE AllocModMem (descSize, modSize: INTEGER; VAR descAdr, modAdr: INTEGER);
   PROCEDURE DeallocModMem (descSize, modSize, descAdr, modAdr: INTEGER);
   PROCEDURE IsReadable (from, to: INTEGER): BOOLEAN;
   PROCEDURE Allocated (): INTEGER;
   PROCEDURE Used (): INTEGER;
   PROCEDURE Root (): INTEGER;
   PROCEDURE NewRec (typ: INTEGER): INTEGER;
   PROCEDURE NewArr (eltyp, nofelem, nofdim: INTEGER): INTEGER;
   PROCEDURE NewObj (VAR o: SYSTEM.PTR; t: Type);
   PROCEDURE AddRef (p: INTEGER): INTEGER;
   PROCEDURE Release (p: INTEGER): INTEGER;
   PROCEDURE Release2 (p: INTEGER): INTEGER;
   PROCEDURE Collect;
   PROCEDURE FastCollect;
   PROCEDURE WouldFinalize (): BOOLEAN;
   PROCEDURE ThisFinObj (VAR id: Identifier): ANYPTR;
 
   PROCEDURE SetLoaderHook (h: LoaderHook);
   PROCEDURE ThisLoadedMod (IN name: ARRAY OF SHORTCHAR): Module;
   PROCEDURE ThisMod (IN name: ARRAY OF CHAR): Module;
   PROCEDURE LoadMod (IN name: ARRAY OF CHAR);
   PROCEDURE GetLoaderResult (OUT res: INTEGER; OUT importing, imported, object: ARRAY OF CHAR);
   PROCEDURE ThisObject (mod: Module; name: ARRAY OF SHORTCHAR): Object;
   PROCEDURE ThisDesc (mod: Module; fprint: INTEGER): Object;
   PROCEDURE ThisField (rec: Type; name: ARRAY OF SHORTCHAR): Object;
   PROCEDURE ThisCommand (mod: Module; name: ARRAY OF SHORTCHAR): Command;
   PROCEDURE ThisType (mod: Module; name: ARRAY OF SHORTCHAR): Type;
   PROCEDURE TypeOf (IN rec: ANYREC): Type;
   PROCEDURE LevelOf (t: Type): SHORTINT;
   PROCEDURE GetObjName (mod: Module; obj: Object; VAR name: Name);
   PROCEDURE GetTypeName (t: Type; VAR name: Name);
   PROCEDURE RegisterMod (mod: Module);
   PROCEDURE UnloadMod (mod: Module);
   PROCEDURE SearchProcVar (var: INTEGER; VAR m: Module; VAR adr: INTEGER);
   PROCEDURE GetRefProc (VAR ref, adr: INTEGER; VAR name: Name);
   PROCEDURE GetRefVar (VAR ref: INTEGER; VAR mode, form: SHORTCHAR;
VAR desc: Type; VAR adr: INTEGER; VAR name: Name);
   PROCEDURE SourcePos (mod: Module; codePos: INTEGER): INTEGER;
 
 END Kernel.

Модуль ядра Kernel реализует поддержку времени выполнения для приложений BlackBox. Эта поддержка включает в себя управление памятью, сбор мусора, управление загруженными модулями (загрузка модулей из объектных файлов реализована отдельно, в загрузчике StdLoader), доступ к метаинформации модулей, дескрипторам типов, символьной отладочной информации, а также обработку исключений.

Средства ядра являются низкоуровневыми (хотя и платформенно независимыми). Используйте прямой импорт ядра только в особых случаях и в минимальном числе модулей своих приложений. Для работы с метаинформацией используйте модуль Meta, для принудительного сбора мусора — модуль Services и т.п.

Вспомогательные средства

CONST nameLen
Определяет длину типа Name, т.е. максимальную длину символьных имен для модулей и сущностей в модулях.

CONST littleEndian
Определяет порядок байт в целых числах, принятый на текущей аппаратной платформе. TRUE соответствует инверсному порядку байт, используемому в архитектуре x86. Используется модулями отладчика, а также модулем Stores, для обеспечения формата файлов хранилища, независимого от платформы.

CONST timeResolution
Число тиков системного таймера, соответствующее одной секунде.

CONST processor
Текущая аппаратная платформа. Значение 10 соответствует платформе x86.

CONST objType
Тип кодовых файлов среды (стандартно ocf, «Oberon Code File»).

CONST symType
Тип символьных файлов среды (стандартно osf, «Oberon Symbol File»).

CONST docType
Тип файлов документов среды (стандартно odc, «Oberon Document»).

PROCEDURE SplitName (name: ARRAY OF CHAR; VAR head, tail: ARRAY OF CHAR)
Выделяет из имени name имя подсистемы head, включающее в себя начало имени до первой смены регистра, и всю остальную часть tail.

PROCEDURE MakeFileName (VAR name: ARRAY OF CHAR; type: ARRAY OF CHAR)
Формирует имя файла из имени name и расширения типа type.

PROCEDURE Time (): LONGINT
Возвращает число тиков системного таймера.

PROCEDURE Beep
Выдает системный звуковой сигнал.

Ниже представлена группа функций для работы с динамическими библиотеками операционной системы.

PROCEDURE LoadDll (IN name: ARRAY OF SHORTCHAR; VAR ok: BOOLEAN)
Выполняет загрузку в память динамическую библиотеку с именем name.

PROCEDURE ThisDllObj (mode, fprint: INTEGER; IN dll, name: ARRAY OF SHORTCHAR): INTEGER
Возвращает адрес объекта с именем name из динамической библиотеки dll. mode определяет тип объекта: 1 - константа, 2 - тип, 3 - переменная, 4 - процедура. ОС Windows, как и большинство других распространенных ОС, поддерживает экспорт динамическими библиотеками только процедур. Метка-отпечаток fprint может использоваться для контроля соответствия типа запрашиваемого объекта, однако в настоящий момент ни одна из ОС кроме систем Оберон-семейства данный механизм не поддерживает.

Обработка исключений

VAR trapCount-: INTEGER
Показывает число исключений, произошедших с момента запуска приложения.

VAR err-, val-: INTEGER
Информация о последнем исключении - код ошибки err и дополнительная информация об ошибке val.

Таблица кодов ошибок

129 -- непредусмотренный тип WITH -- invalid WITH
130 -- непредусмотренный вариант CASE -- invalid CASE
131 -- процедура-функция без RETURN -- function without return
132 -- несоответствие типа -- type guard
133 -- подразумеваемое несоответствие типа -- implied type guard
134 -- переполнение значения -- value out of range
135 -- выход за границы массива -- index out of range
136 -- слишком длинная строка -- string too long
137 -- переполнение стека -- stack overflow
138 -- переполнение разрядов целого -- integer overflow
139 -- деление на нуль -- division by zero
140 -- бесконечный вещественный результат -- infinite real result
141 -- нижнее вещественное переполнение -- real underflow
142 -- верхнее вещественное переполнение -- real overflow
143 -- неопределенный вещественный результат -- undefined real result
144 -- ошибка вещественной арифметики -- not a number
200 -- прерывание с клавиатуры -- keyboard interrupt
201 -- обращение по недопустимому адресу -- NIL dereference
202 -- недопустимая инструкция -- illegal instruction, val содержит код инструкции
203 -- чтение по недопустимому адресу -- illegal memory read,
          val содержит адрес, по которому была произведена попытка чтения
204 -- запись по недопустимому адресу -- illegal memory write,
          val содержит адрес, по которому была произведена попытка записи
205 -- вызов процедуры по недопустимому адресу -- illegal execution,
          val содержит адрес, по которому была произведена попытка передачи управления
257 -- недостаточно памяти -- out of memory
10001H -- аппаратная ошибка шины -- bus error
10002H -- аппаратная ошибка адресации -- address error
10007H -- аппаратная ошибка сопроцессора -- fpu error

<отрицательные значения> – неопределенные программные исключения (например, внешних DLL)

<другие значения> -- нарушения утверждений и остановы по HALT для них действуют соглашения:
128 -- прерывание работы без отображения сообщения об ошибке (аналог исключения EAbort в Delphi)
126 -- процедура еще не реализована -- not yet implemented
125 -- процедура устарела -- call of obsolete procedure
100..124 -- нарушение инварианта -- invariant violated
60..99 -- нарушение постусловия -- postcondition violated
20..59 -- нарушение предусловия -- precondition violated
0..19 -- временные отладочные утверждения и остановы

VAR pc-, sp-, fp-, stack-: INTEGER
Состояние потока в момент последнего исключения.

  • pc - указатель инструкции
  • sp - указатель вершины стека
  • fp - указатель кадра стека
  • stack - указатель начала стека

Регистрация обработчиков и др.

PROCEDURE InstallReducer (r: Reducer)
Регистрирует редуктор памяти - действие, которые выполняется при недостатке памяти в куче. Оно может включать в себя освобождение каких-либо служебных буферов и т.п. Действие выполняется только единожды, после чего редуктор удаляется из списка. Редуктор может перерегистрировать сам себя.

TYPE Reducer
ABSTRACT
Редуктор памяти, выполняющий однократное действие по ее освобождению.

PROCEDURE (r: Reducer) Reduce (full: BOOLEAN)
NEW, ABSTRACT
Процедура, выполняющая действие по освобождению памяти (и, возможно, перерегистрирующая редуктор через InstallReducer).

PROCEDURE InstallCleaner (p: Command)
Регистрирует процедуру-сборщик, которая выполняет периодическое освобождение ресурсов («высокоуровневый сбор мусора»). Такая процедура вызывается каждый раз при выполнении процедуры глобальной очистки Kernel.Cleanup. Процедура-сборщик может, например, выполнять закрытие баз данных, обнуление указателей на временные вспомогательные объекты, и т.п.

PROCEDURE RemoveCleaner (p: Command)
Удаляет ранее зарегистрированную процедуру-сборщик.

PROCEDURE Cleanup
Выполняет сборку ресурсов, вызывая все зарегистрированные процедуры-сборщики. В стандартной версии среды выполняется также сборка мусора (Kernel.Collect), поскольку модуль графического интерфейса HostMenus регистрирует спец. сборщик, вызывающий, в свою очередь, Kernel.Collect.

Следующая группа процедур служит для регистрации различных обработчиков исключений.

PROCEDURE InstallTrapViewer (h: Handler)
Регистрирует процедуру структурного дампа. Обычно регистрация выполняется модулем DevDebug, или, при его отсутствии в конечном приложении, модулем StdDebug. Обработчик регистрируется в единичном экземпляре, глобально для всех задач.

PROCEDURE InstallTrapChecker (h: Handler)
Регистрирует процедуру - обработчик исключений для текущей задачи. Используется модулем Views для обнаружения и отключения отображений, вызвавших сбой (invalid views). Обработчик регистрируется в единичном экземпляре, для текущей задачи.

PROCEDURE PushTrapCleaner (c: TrapCleaner)
Помещает сборщик в список обработки исключения текущей задачи. В случае исключения будут вызваны процедуры всех установленных сборщиков, которые могут корректно осободить ресурсы и выполнить любые другие действия.

TYPE TrapCleaner
ABSTRACT
Сборщик ресурсов при исключении.

PROCEDURE (c: TrapCleaner) Cleanup
NEW, EMPTY
Действие, которое будет выполнено при исключении в текущей задаче.

PROCEDURE PopTrapCleaner (c: TrapCleaner)
Удаляет сборщик из списка обработки исключения текущей задачи.

PROCEDURE Start (code: Command)
Запуск процедуры code рабочего цикла приложения (в графической версии среды - HostMenus.Loop). (Вызов Start необходим для снятия блокировки с загрузчика модулей, поскольку при запуске рабочего цикла секция инициализации модуля никогда не возвращает управление. Кроме того, структурный дамп стека выдается, начиная с вызова Start, все предыдущие активации процедур относятся к этапу инициализации среды и не отображаются).

Предусловие
вызывается из главного потока приложения 20

PROCEDURE Quit (exitCode: INTEGER)
Выход из приложения. Для всех активных задач выставляется флаг завершения. После максимального ожидания в 5 секунд выполняется остановка неотвечающих задач и их закрытие. Далее выполняется выход из процесса приложения.

PROCEDURE FatalError (id: INTEGER; str: ARRAY OF CHAR)
Немедленный выход из процесса приложения в случае фатальной ошибки. В id передается номер ошибки, в str - комментарий.

PROCEDURE SetTrapGuard (on: BOOLEAN)
TRUE отключает показ окна дампа в случае исключения.

PROCEDURE Try (h: TryHandler; a, b, c: INTEGER)
Выполнить процедуру h с обработкой исключений. a, b, c - параметры, передаваемые в процедуру. В случае, если h вызывает исключение, выполнение продолжается со следующей команды после вызова Try. Также показывается окно структурного дампа.

PROCEDURE InterfaceTrapHandler (excpRec, estFrame, context, dispCont: INTEGER): INTEGER
[Специфично для Direct-To-COM]
Процедура системного назначения, применяется для обработки исключений COM, обращение к ней генерируется компилятором BlackBox. Не предназначена для использования разработчиками.

Диспетчер памяти

TYPE Block
[untagged], неэкспортирован
Структура блока памяти любого динамического объекта. Несмотря на то, что тип не экспортирован, его неявный «экспорт» подразумевается тем, что идентичные объявления используются в других системных и отладочных модулях среды (например, DevHeapSpy, DevDebug и т.п.).

tag: Type
Поле tag располагается по смещению -4 от указателя на динамический объект. Для объектов-записей тег хранит адрес описателя типа Kernel.Type. Для объектов-массивов тег хранит адрес описателя базового элемента (для элементарных типов в ядре объявлены псевдоописатели, имеющие идентичный размер), к которому прибавляется бит {1} (т.е. выполняется побитовый OR с числом 2). Поскольку адреса описателей выровнены по смещению 4 и более байт, такая метка позволяет однозначно идентифицировать в памяти динамический объект, являющийся массивом. Для динамических объектов - записей начиная со смещения 0 от указателя идут собственные поля записи, определенные в ее типе. Для массивов вводятся следующие поля:

last: INTEGER
Указатель на последний элемент массива.

actual: INTEGER
Вспомогательное поле, используется при сборке мусора.

first: INTEGER
Указатель на первый элемент массива. Для динамических массивов переменной длины после поля first следуют N целых чисел, задающих кол-во элементов в каждом измерении данного динамического массива, i-е число возвращается функцией LEN(array, i). Таким образом, число измерений динамического массива переменной длины определяется выражением dim := (block.first - S.ADR(array) - 3*SIZE(INTEGER)) DIV 4.

Для динамических массивов фиксированной длины далее следуют элементы массива. Условие block.first - 3*4 = S.ADR(array) определяет, что массив является динамическим массивом фиксированной длины. Для многомерных массивов тип базового элемента - массив (т.е. многомерный массив трактуется как массив массивов).

PROCEDURE AllocModMem (descSize, modSize: INTEGER; VAR descAdr, modAdr: INTEGER)
Запрашивает у операционной системы блок памяти под загружаемый модуль. descSize - размер секции описаний, modSize - размер секции данных и кода. Возвращает в descAdr и modAdr адреса соответственно секции описаний и секции данных и кода. Вызывается загрузчиком модулей (по умолчанию - StdLoader).

PROCEDURE DeallocModMem (descSize, modSize, descAdr, modAdr: INTEGER)
Освобождает память, выделенную под модуль.

PROCEDURE IsReadable (from, to: INTEGER): BOOLEAN
Проверяет области памяти [from, to] на доступность для чтения.

PROCEDURE Allocated (): INTEGER
Возвращает объем памяти, занимаемый всеми динамическими объектами.

PROCEDURE Used (): INTEGER
Возвращает объем памяти, выделенный операционной системой под кучу BlackBox.

PROCEDURE Root (): INTEGER
Возвращает указатель на начало списка кластеров кучи BlackBox. Структура кучи определена специальными неэкспортированными типами (Cluster, Block), которые объявлены в исходном коде ядра и исходном коде других системных и отладочных модулей (например, DevDebug, DevHeapSpy).

PROCEDURE NewRec (typ: INTEGER): INTEGER
Поддержка встроенной функции NEW для записей. Создает новую запись типа typ. typ - тег типа, то есть, адрес некоторого дескриптора Kernel.Type.

PROCEDURE NewArr (eltyp, nofelem, nofdim: INTEGER): INTEGER
Поддержка встроенной функции NEW для динамических массивов. Создает новый массив с базовым типом элементов eltyp, общим числом элементов nofelem (определяемым как произведение длин всех измерений массива) и числом измерений nofdim. Если nofdim = 0, то создается массив фиксированной длины (число измерений такого массива известно только компилятору при генерации кода). Для массивов динамической длины размер массива в каждом измерении заполняется самостоятельно (см. выше описание структуры блока Block).

PROCEDURE NewObj (VAR o: SYSTEM.PTR; t: Type)
PROCEDURE AddRef (p: INTEGER): INTEGER
PROCEDURE Release (p: INTEGER): INTEGER
PROCEDURE Release2 (p: INTEGER): INTEGER
[Специфично для Direct-To-COM]
Процедуры системного назначения, применяются для создания и подсчета ссылок COM-объектов, обращения к ним генерируются компилятором BlackBox. Не предназначены для использования разработчиками.

Сборка мусора и финализация

PROCEDURE Collect
Выполнить сборку мусора и вызвать все финализаторы.

PROCEDURE FastCollect
Выполнить сборку мусора без вызова финализаторов. Объекты с финализаторами не удаляются, а помещаются в специальную очередь ожидания финализации, которая будет обработана при вызове Collect.

PROCEDURE WouldFinalize (): BOOLEAN
Есть ли в очереди объекты, ожидающие финализации.

PROCEDURE ThisFinObj (VAR id: Identifier): ANYPTR
Выполняет поиск по некоторому критерию среди всех экземпляров некоторого типа, который имеет финализатор. Такой поиск возможен, поскольку для всех экземпляров типов, имеющих финализатор, ядро поддерживает специальный служебный список. Критерий поиска определяется переданным экземпляром типа, расширенного от Identifier. Возвращается требуемый объект или NIL, если такой объект не найден.

TYPE Identifier
ABSTRACT
Критерий поиска для ThisFinObj.

typ: INTEGER
Тег типа объектов, среди которых ведется поиск.

obj-: ANYPTR
Очередной объект данного типа.

PROCEDURE (VAR id: Identifier) Identified (): BOOLEAN
NEW, ABSTRACT
Процедура, которая должна быть расширена для обработки множества объектов заданного типа и выбора искомого. Процедура должна проверить объект obj и вернуть TRUE, если найден требуемый объект, и FALSE в противном случае.

Работа с метаданными

TYPE Module
[untagged]
Структура с информацией о модуле. Модуль состоит из нескольких секциий. Секция описаний включает в себя заголовок модуля и описатели его типов. Секция кода содержит исполняемый код процедур модуля. Секция данных содержит глобальные переменные модуля. Секция символьной информации содержит имена и описания неэкспортированных сущностей модуля: имена процедур, локальных переменных и параметров, имена неэкспортированных переменных и т.п. Эта информация используется, например, отладчиком. При выгрузке модуля выгружаются последние три секции, в то время как секция описаний остается в памяти, поскольку в куче могут существовать экземпляры типов уже выгруженного модуля. Стандартный загрузчик StdLoader загружает секции непосредственно из файла монолитным блоком, после чего в известных точках блока проводится настройка ссылок с учетом смещения модуля в памяти.

next-: Module
Указатель на следующий модуль в списке.

name-: Name
Символьное имя модуля.

opts-: SET
Свойства модуля. Флаги из диапазона 0..15 выставляются компилятором, 16..31 - ядром и загрузчиком.

  • init – 16 – модуль был инициализирован
  • dyn – 17 – модуль загружен динамически
  • dll – 18 – модуль представляет собой интерфейс к динамической библиотеке ОС
  • iptrs – 30 – в секции данных модуля содержатся ссылки на COM-объекты

Информацию по флагам компилятора см. в спецификациях (директория Dev/Spec) и исходных кодах подсистемы Dev.

refcnt-: INTEGER
Число ссылок на модуль, то есть, число загруженных в настоящий момент модулей, импортирующих данный. Если refcnt = 0, то модуль ничем не импортируется и может быть выгружен. Однако следует учитывать, что модуль может использоваться неявно. Например, модуль реализации может инсталлировать свои фабрики в некоторый абстрактный модуль, но при этом сам он не импортируется никаким модулем. При выгрузке такого модуля и последующему обращению к фабрике в абстрактном модуле произойдет ошибка. Если refcnt < 0, то модуль уже выгружен из памяти. Однако при этом в памяти остается вся информация о типах данного модуля, поскольку еще могут существовать динамические экземпляры этих типов с соотв. тегом. Таким образом, в списке модулей может находиться несколько версий модуля с одним именем, но только для одного из них refcnt >= 0, то есть, загружены его секция данных и кода.

compTime-, loadTime-: ARRAY 6 OF SHORTINT
Время, когда модуль был откомпилирован и загружен в память соответственно. Формат - ГМДЧМС.

ext-: INTEGER
Зарезервировано.

term-: Command
Адрес секции финализации модуля.

nofimps-: INTEGER
Количество модулей, импортируемых данным модулем.

imports-: POINTER TO ARRAY [untagged] OF Module
Список модулей, импортируемых данным модулем.

export-: Directory
Каталог сущностей, экспортируемых модулем.

csize-, dsize-, rsize-: INTEGER
Размеры секции кода, секции данных и секции символьной информации соответственно.

code-, data-, refs-: INTEGER
Указатели на начало секции кода, секции данных и секции символьной информации соответственно. (Для текущей реализации компилятора BlackBox переменные в секции данных располагаются в порядке, обратном порядку их объявления в исходном коде).

procBase-, varBase-: INTEGER
Базовые адреса для вычисления смещений процедур и переменных соответственно.

nofptrs-: INTEGER
Число переменных-указателей в секции данных модуля.

ptrs-: POINTER TO ARRAY [untagged] OF INTEGER
Список смещений переменных-указателей относительно varBase. Используется, в частности, при сборке мусора.

names-: POINTER TO ARRAY [untagged] OF SHORTCHAR
Список символьных имен сущностей модуля.

TYPE Type
[untagged]
Описатель типа данных. Хранит информацию о размере и структуре данных. Указатели на связанные процедуры типа находятся по отрицательным смещениям от описателя. Указатель на n-й метод находится по смещению -4 * (n + 1).

size-: INTEGER

  • Для типа записей: размер
  • Для типов массивов фиксированной длины: количество элементов в первом измерении. Если массив фиксированной длины многомерный, то он трактуется как одномерный массив с типом элементов «массив» и т.д.
  • Для типов массивов динамической длины: 0
  • Для типов процедур: отпечаток (fingerprint) сигнатуры процедуры

mod-: Module
Модуль, в котором определен тип данных.

id-: INTEGER
Свойства типа в упакованном виде.

  • x1 – form – форма типа
    • 0 - процедура 1 - запись 2 - массив 3 - указатель
  • x4 – attributes – атрибуты типа
    • для записей: 0 - final 1 - extensible 2 - limited 3 - abstract
  • x16 – level
    • для записей: количество базовых типов в иерархии
    • для динамических и открытых массивов: количество измерений
  • x256 – nameIndex – индекс имени типа (позиция в mod.names)

base-: ARRAY 16 OF Type

  • Для записей - массив указателей на дескрипторы базовых типы соотв. уровней.
    • base[0] - самый первый базовый тип, …, base[id DIV 16 MOD 16 - 1] - неспосредственный предок)
  • Для массивов - base[0] хранит указатель на дескриптор типа элементов или код одного из базовых типов.
  • Для указателей - base[0] хранит указатель на дескриптор целевого типа.

fields-: Directory
Каталог полей записи.

ptroffs-: ARRAY .. OF INTEGER
Для записей - список смещений полей-указателей. Используется сборщиком мусора. Конец списка обозначается отрицательным значением.

TYPE Directory
[untagged]
Каталог сущностей (экспортируемых модулем или полей записей). Каталог сущностей модуля содержит описания только экспортированных сущностей. Каталог полей записи содержит описания всех ее полей, в том числе неэкспортированных.

num-: INTEGER
Количество сущностей в каталоге.

obj-: ARRAY .. OF ObjDesc
Список описаний сущностей.

TYPE ObjDesc
[untagged]
Описатель сущности.

fprint-: INTEGER
Отпечаток (fingerprint) сущности, используется механизмом контроля версий.

offs-: INTEGER
Для полей записи - смещение от начала записи. Для типов записей - дополнительный отпечаток (pvfprint).

id-: INTEGER
Свойства сущности в упакованном виде.

  • x1 – mode – вид сущности
    • 1 - константа 2 - тип 3 - переменная 4 - процедура 5 - поле записи
  • x16 – visibility – видимость сущности
    • 1 - скрытая 2 - экспорт только для чтения 3 - (недокументировано) 4 - полный экспорт
  • x256 nameIndex индекс имени сущности (позиция в mod.names).

struct-: Type
Указатель на дескприптор типа сущности или код одного из форматов данных.

Таблица форматов данных

1H BOOLEAN
2H SHORTCHAR
3H CHAR
4H BYTE
5H SHORTINT
6H INTEGER
7H SHORTREAL
8H REAL
9H SET
0AH LONGINT
0BH ANYREC
0CH ANYPTR
0DH SYSTEM.PTR
0EH PROCEDURE
0FH STRING (для констант)
11H RECORD
12H ARRAY
13H POINTER TO RECORD или POINTER TO ARRAY
-1 [специфично для Direct-To-COM Compiler] — указатель на COM-объект
20H [специфично для Direct-To-COM Compiler] — COM.IUnknown
21H [специфично для Direct-To-COM Compiler] — COM.GUID
22H [специфично для Direct-To-COM Compiler] — COM.RESULT

PROCEDURE ThisObject (mod: Module; name: ARRAY OF SHORTCHAR): Object
Возвращает указатель на описатель сущности с именем name в модуле mod.

PROCEDURE ThisDesc (mod: Module; fprint: INTEGER): Object
Возвращает указатель на описатель сущности с отпечатком fprint в модуле mod.

PROCEDURE ThisField (rec: Type; name: ARRAY OF SHORTCHAR): Object
Возвращает указатель на описатель поля с именем name типа записи rec.

PROCEDURE ThisType (mod: Module; name: ARRAY OF SHORTCHAR): Type
Возвращает указатель на дескриптор экспортированного типа с именем name в модуле mod.

PROCEDURE ThisCommand (mod: Module; name: ARRAY OF SHORTCHAR): Command
Возвращает указатель на процедуру без параметров («команду») с именем name в модуле mod.

PROCEDURE TypeOf (IN rec: ANYREC): Type
Возвращает указатель на дескриптор типа записи rec.

PROCEDURE LevelOf (t: Type): SHORTINT
Возвращает уровень расширения (то есть, число базовых типов в иерархии) для типа t.

PROCEDURE GetObjName (mod: Module; obj: Object; VAR name: Name)
Возвращает имя объекта obj в модуле mod.

PROCEDURE GetTypeName (t: Type; VAR name: Name)
Возвращает имя типа t.

PROCEDURE SearchProcVar (var: INTEGER; VAR m: Module; VAR adr: INTEGER)
Возвращает модуль m и смещение adr относительно m.code для процедуры с адресом var.

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

PROCEDURE GetRefProc (VAR ref, adr: INTEGER; VAR name: Name)
Позволяет просканировать символьную информацию обо всех процедурах модуля. ref инициализируется стартовым адресом секции символьной информации целевого модуля (ref = mod.refs), для перечисления всех процедур GetRefProc вызывается, пока adr # 0. Для текущей процедуры adr возвращает ее смещение относительно секции кода модуля (mod.code), name - ее имя.

PROCEDURE GetRefVar (VAR ref: INTEGER; VAR mode, form: SHORTCHAR; VAR desc: Type; VAR adr: INTEGER; VAR name: Name)
Позволяет просканировать символьную информацию о всех переменных модуля и локальных переменных процедур. Для перечисления локальных переменных и параметров процедуры необходимо передать ref, возвращенный процедурой GetRefProc после сканирования целевой процедуры, и вызывать GetRefVar, пока mode # 0X. Глобальные переменные модуля рассматриваются как локальные переменные его процедуры инициализации. Для перечисления глобальных переменных модуля необходимо инициализировать ref стартовым адресом секции символьной информации интересующего модуля (ref = mod.refs), затем однократно вызвать GetRefProc, чтобы перевести ref на процедуру инициализации, и убедиться, что возвращённое значение параметра adr отлично от нуля. После этого следует вызывать GetRefVar, пока mode = 1X.

  • form может принимать значения из таблицы форматов данных (см. выше)
  • desc - указатель на дескприптор типа для записей, указателей и массивов
  • name- имя переменной
  • Для глобальных переменных:
    • mode = 1
    • adr - смещение переменной относительно начала секции данных модуля (mod.data)
  • Для локальных переменных:
    • mode может принимать два значения:
      • 1 - для локальной переменной или параметра-значения
      • 3 - для параметра-ссылки (VAR, IN, OUT)
    • adr - смещение относительно кадра стека,
    • для переменных adr < 0, для параметров adr > 0.

PROCEDURE SourcePos (mod: Module; codePos: INTEGER): INTEGER
Возвращает позицию в исходном коде для машинной инструкции. mod - модуль, codePos - смещение от начала секции кода модуля (mod.code).

TYPE ItemExt
TYPE ItemAttr
Типы используются для расширения модуля метапрограммирования Meta.

Динамическая загрузка модулей

CONST done, fileNotFound, syntaxError, objNotFound, illegalFPrint, cyclicImport, noMem, commNotFound, commSyntaxError, moduleNotFound
Коды ошибок, возвращаемые загрузчиком модулей.

VAR modList-: Module
Список модулей, которые были загружены. Содержит в том числе описатели уже выгруженных модулей - см. выше описание типа Module.

PROCEDURE ThisMod (IN name: ARRAY OF CHAR): Module
Возвращает указатель на описатель модуля с именем name. Если модуль еще не загружен, то загружает его.

PROCEDURE ThisLoadedMod (IN name: ARRAY OF SHORTCHAR): Module
Возвращает указатель на описатель модуля с именем name, если модуль уже загружен. В противном случае возвращает NIL.

PROCEDURE LoadMod (IN name: ARRAY OF CHAR)
Загружает модуль с именем name.

PROCEDURE UnloadMod (mod: Module)
Выгружает модуль mod, если нет загруженных модулей, которые его импортируют.

PROCEDURE GetLoaderResult (OUT res: INTEGER; OUT importing, imported, object: ARRAY OF CHAR)
Возвращает результат последней попытки загрузки модуля (для текущего потока).

  • res - код ошибки, см. выше список констант.
  • importing, imported, object - имена модулей и сущностей, вызвавших ошибку при загрузке модуля.

TYPE LoaderHook (Kernel.Hook)
ABSTRACT
Базовый тип для реализации загрузчика объектных файлов.

PROCEDURE (h: LoaderHook) ThisMod (IN name: ARRAY OF SHORTCHAR): Kernel.Module
NEW, ABSTRACT
Возвращает указатель на описатель модуля с именем name. Если модуль не загружен, то должна выполняться его загрузка из объектного файла или иного источника (например, сетевого репозитория). Загрузчик должен выделить память под модуль процедурой Kernel.AllocModMem и загрузить в выделенную область все секции модуля. Затем должна быть вызвана процедура Kernel.RegisterMod для регистрации загруженного модуля.

PROCEDURE (h: LoaderHook) Res (): INTEGER
NEW, ABSTRACT
Возвращает результат последней попытки загрузки модуля (для текущего потока).

PROCEDURE (h: LoaderHook) Info (OUT importing, imported, object: ARRAY OF CHAR)
NEW, ABSTRACT
Возвращает дополнительную информацию - имена модулей и сущностей, вызвавших ошибку при загрузке модуля.

PROCEDURE (h: LoaderHook) ResDone
NEW, ABSTRACT
Сбрасывает результат загрузчика в done.

PROCEDURE SetLoaderHook (h: LoaderHook)
Инсталлирует в ядре реализацию загрузчика объектных файлов. По умолчанию используется загрузчик StdLoader.

PROCEDURE RegisterMod (mod: Module)
Вызывается загрузчиком после загрузки модуля в память для регистрации модуля в ядре.

© 2005-2017 OberonCore и коллектив авторов.