Size: a a a

Compiler Development

2020 July 09

c

cevek in Compiler Development
ну это в момент имплементации класса можно ругнуть что у нас конфликт имен полей
источник

AT

Alexander Tchitchigi... in Compiler Development
cevek
ну это в момент имплементации класса можно ругнуть что у нас конфликт имен полей
Таблица виртуальных функций — одна для всех объектов данного класса. Так что если мы туда засунем поле — это будет (статическое) поле класса, а не объекта. Но статические поля класса — это и так просто глобальные переменные, так что для них таблица не нужна.
источник

c

cevek in Compiler Development
это понятно, но ведь ничто не мешает положить в эту таблицу и смещение полей
источник

c

cevek in Compiler Development
ведь все поля в разных инстансах одного класса имеют одно смещение же?
источник

AT

Alexander Tchitchigi... in Compiler Development
cevek
ведь все поля в разных инстансах одного класса имеют одно смещение же?
Да, но смещение относительно чего? Смещение фиксировано и известно относительно "начала объекта", но таблица методов может быть смещена на разное смещение от начала для разных объектов, так что относительно неё все смещения вне таблицы могут быть какими попало.
источник

ВМ

Виталий Медоваров... in Compiler Development
поля при наследовании складываются последовательно от разных родительских классов
источник

ВМ

Виталий Медоваров... in Compiler Development
у тебя же может быть много интерфейсов с полями
источник

AT

Alexander Tchitchigi... in Compiler Development
Кроме того, получится как минимум double indirection, что gets old pretty quickly. В смысле, сильно портит кеши и предсказание переходов.
источник

AT

Alexander Tchitchigi... in Compiler Development
Но в Swift, кажется, делают что-то такое в ограниченных масштабах — можно глянуть что именно и как.
источник

c

cevek in Compiler Development
ну я имел ввиду такое
obj = [/*поля интерфейса А*/a, b, c, /*поля интерфейса B*/, c, d, e]
obj[Ashift + 2] = 1
obj[Bshift + 1] = 2
источник

AT

Alexander Tchitchigi... in Compiler Development
cevek
ну я имел ввиду такое
obj = [/*поля интерфейса А*/a, b, c, /*поля интерфейса B*/, c, d, e]
obj[Ashift + 2] = 1
obj[Bshift + 1] = 2
Тут два режима. Либо мы знаем конкретный фактический класс объекта, и тогда нам плевать на таблицы, мы и так знаем где что лежит. Либо всё что мы знаем — это указатель на таблицу, и тогда мы понятия не имеем в каком месте какого фактического объекта она торчит, и, соответственно, что вокруг неё и по каким смещениям.
источник

AZ

Alexander Zalutskiy in Compiler Development
Alexander Tchitchigin
Тут два режима. Либо мы знаем конкретный фактический класс объекта, и тогда нам плевать на таблицы, мы и так знаем где что лежит. Либо всё что мы знаем — это указатель на таблицу, и тогда мы понятия не имеем в каком месте какого фактического объекта она торчит, и, соответственно, что вокруг неё и по каким смещениям.
Теоретически можно передавать таблицу интерфейса и начало объекта. А в таблице хранить смещения относительно начала объекта
источник

AZ

Alexander Zalutskiy in Compiler Development
Да, будут дублирования для каждого интерфейса если они пересекаются
источник

AZ

Alexander Zalutskiy in Compiler Development
Но можно
источник

c

cevek in Compiler Development
Alexander Tchitchigin
Тут два режима. Либо мы знаем конкретный фактический класс объекта, и тогда нам плевать на таблицы, мы и так знаем где что лежит. Либо всё что мы знаем — это указатель на таблицу, и тогда мы понятия не имеем в каком месте какого фактического объекта она торчит, и, соответственно, что вокруг неё и по каким смещениям.
вроде же все тоже самое что ты мне показывал?
function x(A g) {return g.a}
x(rand() ? new Foo() : new Bar)

function x(ptr) {return ptr + a_shift_in_A}
x(rand() ? fooPtr + A_shift_in_Foo : barPtr + A_shift_in_Bar)
источник

AT

Alexander Tchitchigi... in Compiler Development
cevek
вроде же все тоже самое что ты мне показывал?
function x(A g) {return g.a}
x(rand() ? new Foo() : new Bar)

function x(ptr) {return ptr + a_shift_in_A}
x(rand() ? fooPtr + A_shift_in_Foo : barPtr + A_shift_in_Bar)
Теперь
Foo layout:
X_vtable
A_vtable
B_vtable
field_foo : i32

Bar layout:
A_vtable
C_vtable
Y_vtable
fielf_foo : i32

Что куда нужно записать чтобы добраться до field_foo в каждом из объектов? И это ещё не самы сложный layout.
источник

c

cevek in Compiler Development
field_foo он к какому интерфейсу относится?
источник

AT

Alexander Tchitchigi... in Compiler Development
cevek
field_foo он к какому интерфейсу относится?
Мы же уже пришли к заключению, что он не может физически принадлежать интерфейсу, а должен быть расположен в самом объекте (вне виртуальных таблиц). Что должно быть в интерфейсе (виртуальной таблице) A, чтобы получать доступ к нужному полю вне зависимости от фактического класса объекта?
источник

c

cevek in Compiler Development
интерфейс просто содержит список имен своих полей с типами и смещениями относительно 0
источник

c

cevek in Compiler Development
компилятор когда видит поле a из интерфейса A то он подставляет это число

A obj = new Bar() // barPtr + A_shift_in_Bar
obj.a // objPtr + a_shift_in_A
источник