ucl internals

Jul 05, 2016 06:43

Понял, что мне очень сильно не нравится пухлое представление самых частоупотребимых сущностей: коротких чисел и символов.

Я не проводил никаких исследований на эту тему, но что-то мне подсказывает, что весьма существенная часть реальных переменных, используемых в эмбеде - 16-битные. Размеры буферов, индексы внутри них, разрешение дисплеев, скорости перемещения и т.п., и т.д. - всё это чаще представимо в виде небольших чисел, высокая разрядность тут ни к чему, да и дорого. Кроме этого, существенная часть всяких рабочих переменных записывается в виде одно-, двух- и трёхбуквенных мнемоник, типа x, v1, lst и так далее. То есть имеет смысл подумать над максимально компактным представлением некоторых данных (сохранив, разумеется, возможность представления более крупных данных в неприкосновенности: 32- и 64-битные числа, равно как и ДлинныеИПонятныеИменаПеременных тоже имеют право быть!).

Хак относится к little-endian машинам минимум 32-битной разрядности. Для адаптации его к big-endian нужно поменять порядок полей в структурах.


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



N

31

30

29

28..24

23..16

15..8

7..0

CAR mnemonic

gc

cons

category

opt

data

data

data

When 0

working

Atomic

container

Atomic options

Misc.data

When 1

garbage

Cons cell

pointer

pointer>>3

CDR

t.b.d.

В том случае, если данные можно полностью уместить внутрь поля data одного такого регистра, представление данных получается таким:



N

31

30

29

28..24

23..0

|← 8 bits →|

CAR mnemonic

gc

cons

category

opt

data

0

0

0

options

Atomic container data

CDR

Not available; has no meaning; don't try to use it

В том случае, если данные можно полностью уместить внутрь ячейки (которая, по традиции, представляет собой пару указателей, но на самом деле не обязательно является парой именно УКАЗАТЕЛЕЙ (просто таков её размер)), представление данных получается немного иным. В поле CAR лежит некое краткое описание типа данных и, опционально, кусочек этих данных (возможно, какие-то служебные сведения), а в поле CDR лежит либо указатель (например, на C-style строку), либо какая-то иная нужная нам порция данных (например, 32-битное число):



N

31

30

29

28..24

23..16

15..0

CAR mnemonic

gc

cons

category

opt

flags

data

0

0

1

options

Atomic flags

Additional atomic data

CDR

Atom's data (also can be pointer with any align)

CONS-ячейка, с учётом этих оптимизаций, выглядит так:



N

31

30

29

28..24

23..16

15..8

7..0

CAR mnemonic

gc

cons

category

opt

data

0

1

0: container

options

Atomic container data

1: pointer

Pointer to CAR; shifted >> 3 (align 8)

CDR mnemonic

-

-

size

opt

data

0: container

options

Atomic container data

1: pointer

Pointer to CDR; shifted >> 3 (align 8)

Низкоуровневый код выглядит несколько странно, но однако же, простенький тяп-ляп тест даёт такой результат:
atomic cell; generic form; [retrieve-long-data, length 18]
atomic cell; short form; [symbol]
atomic container [a4]

В квадратных скобках - гипотетические имена символов. В первом случае имя не помещается ни в указатель, ни даже в ячейку, и хранится в куче как обычная C-строка (в атом же занесён указатель на эту строку). Во втором случае имя не помещается в указатель, но влезает в ячейку, в третьем случае имя полностью уместилось внутрь указателя. Для коротких имён экономия памяти получается весьма существенной, с лихвой окупающая пару дополнительных проверок нескольких битов.

Правильная организация структур данных - залог успеха.

uncommon lisp

Previous post Next post
Up