Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type inference prototype based on static analysis #92

Open
wants to merge 105 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
cd3ffe7
Adds BranchNode for easy operation on branches
0x7CFE Apr 22, 2016
0e68d06
Fixes branch node visualization
0x7CFE Apr 22, 2016
113bed0
Fixes type.txt
0x7CFE Apr 28, 2016
1688a7d
Adds stub for TauLinker
0x7CFE Apr 28, 2016
90b42b2
Refactors GraphWalker to use node colors
0x7CFE May 2, 2016
1dba10d
Adds sample back edge classifier
0x7CFE May 2, 2016
b77dd54
Minor fixes in GraphLinker
0x7CFE May 2, 2016
c91b043
Removes Forward- and Backward- Walkers as violating the LSP
0x7CFE May 2, 2016
8dcb48f
Adds tau node linkage and optimization logic
0x7CFE May 5, 2016
d4a7be7
Adds logic to render tau nodes
0x7CFE May 5, 2016
119c38f
Fixes tau optimizer by handling nodes by pairs
0x7CFE May 7, 2016
6c9105b
Adds accumulated path to GraphWalker, BackEdgeDetector refactoring
0x7CFE May 9, 2016
0b67873
draft: refactors TauLinker to track back edges
0x7CFE May 9, 2016
2fcf67e
Tau nodes now store back edge flag in incoming list
0x7CFE May 9, 2016
7e70c0d
Fixes graph linker in case of assign node first in the domain
0x7CFE May 10, 2016
61a2543
Cleans up control graph visualizer
0x7CFE May 11, 2016
ec1644c
Minor fixes in graph api
0x7CFE May 15, 2016
5b3a637
Adds basic logic of type analyzer and inference API
0x7CFE May 15, 2016
44a1370
Adds Type::toString()
0x7CFE May 15, 2016
3ac8c0a
Adds CallContext::operator[index]
0x7CFE May 15, 2016
97ea0cb
Adds const cast for BranchNode
0x7CFE May 16, 2016
d6db564
Fixes analyzer and context, adds handling of conditional branches
0x7CFE May 16, 2016
3a66f0c
Adds order, comparison and composition operators to the Type
0x7CFE May 21, 2016
1cc3e65
Hides trace messages in ControlGraph under condition
0x7CFE May 21, 2016
12d5460
Adds meta information to control graph
0x7CFE May 21, 2016
6c8a069
Adds core inference logic to TypeAnalyzer
0x7CFE May 21, 2016
3adc4dc
Fixes asserts
0x7CFE May 21, 2016
4a921d9
Adds more inference logic
0x7CFE May 21, 2016
d53e50d
Adds inference for instantiation and get class primitives
0x7CFE May 23, 2016
998d38a
Adds temporary solution for several SmallInt primitives
0x7CFE May 23, 2016
752e88e
Adds function to print block type
0x7CFE May 25, 2016
4e40ce8
Renames CallContext to InferContext, analyzeCall to inferMessage
0x7CFE May 25, 2016
f83fa6a
Removes findCallContext()
0x7CFE May 25, 2016
8c9cf68
Adds stub for block inference
0x7CFE May 25, 2016
ed3415a
Adds logic to infer messages to literal classes
0x7CFE May 25, 2016
d92e33f
Adds inference for block invocation arguments
0x7CFE May 25, 2016
a5bc8c5
Fixes subtypes in array context
0x7CFE May 26, 2016
b3953db
Disambiguates subtype fill functions
0x7CFE May 31, 2016
ec073fd
Adds more small int primitives (still temporary solution)
0x7CFE May 31, 2016
cae2904
Collects graph meta info during graph construction
0x7CFE May 31, 2016
c7036a5
Fixes prototype of TypeSystem::inferBlock()
0x7CFE May 31, 2016
92cf908
Refactors graph metainfo
0x7CFE Jun 1, 2016
cc62ba0
Adds graph back edges set to metainfo
0x7CFE Jun 1, 2016
37677b7
Adds inference of variables from block's lexical context
0x7CFE Jun 1, 2016
c6003e6
Adds inference of the captured context
0x7CFE Jun 5, 2016
5a8c692
Extracts TauLinker into separate file
0x7CFE Jun 6, 2016
c0f7a53
Adds reverse iterator and eraseTauNodes() to the ControlGraph
0x7CFE Jun 11, 2016
bc2eb8e
Renames TypeAnalyzer::getTypeList() to getTypes()
0x7CFE Jun 11, 2016
d2e3ada
Adds ClosureNode and it's handling in TauLinker
0x7CFE Jun 18, 2016
8536cb3
Adds inference of block closures and caught temporaries
0x7CFE Jun 18, 2016
2ca6f8d
Adds visualization of closure taus
0x7CFE Jun 18, 2016
4b13dbb
Fixes asserts
0x7CFE Jun 18, 2016
ed47820
Adds handling of (Smallint) in arithmetic primitives
0x7CFE Jun 18, 2016
f78ba24
Fixes block invoke primitive
0x7CFE Jun 18, 2016
a612201
Adds inference of the special::sendToSuper instruction
0x7CFE Jun 19, 2016
d3d9262
Fixes ControlGraph::eraseTauNodes()
0x7CFE Jun 20, 2016
197197b
Fixes TauLinker
0x7CFE Jun 20, 2016
9b79157
Fixes inference of the recurring contexts
0x7CFE Jun 23, 2016
649ebe7
Adds TRecursionKind to the InferContext
0x7CFE Jun 23, 2016
6a0b389
Adds TypeSystem::dumpAllContexts()
0x7CFE Jun 23, 2016
5fd6a7d
Adds TypeAnalyzer::dumpTypes()
0x7CFE Jun 23, 2016
aa90705
Fixes Type::operator |= and TypeAnalyzer::processPhi()
0x7CFE Jun 24, 2016
881c62b
Fixes TypeAnalyzer::pushTemporary() by using getArgumentType()
0x7CFE Jun 26, 2016
c08afa6
Adds more primitives to TypeAnalyzer::doPrimitive()
0x7CFE Jun 26, 2016
663dd9c
Fixes TypeAnalyzer::processPhi()
0x7CFE Jun 26, 2016
93142ef
Adds InferContext::getSingleReturnType()
0x7CFE Jun 26, 2016
06b52e4
Fixes Type's comparison operator
0x7CFE Jun 28, 2016
0f311b1
Adds cross-context references
0x7CFE Jun 28, 2016
c856ee5
Adds cacheing for block contexts and for send-to-super
0x7CFE Jun 28, 2016
ecfb6a2
Adds call graph visualizer
0x7CFE Jun 28, 2016
3f85065
Adds Type::flatten() and uses it to flatten phi and method return types
0x7CFE Jul 1, 2016
0bf6f42
Adds handling for throwError, stringAt/Put and blockReturn
0x7CFE Jul 1, 2016
15d4d04
Adds breadth-first graph traversing strategy
0x7CFE Jul 1, 2016
5b7bcb5
Uses breadth-first node walking in TypeAnalyzer::basicRun()
0x7CFE Jul 1, 2016
8290467
Adds special handling of messages that do not return normally
0x7CFE Jul 1, 2016
ce9f0b7
Adds Type::fold(), refactors getSingleReturnType()
0x7CFE Jul 2, 2016
d74c752
Adds caching for block graphs, renames getControlGraph() to getMethod…
0x7CFE Jul 5, 2016
31ff87f
Folds arguments of SmallInt primitives
0x7CFE Jul 5, 2016
63aacb2
Adds helper functions Type::is*() and getQualifiedName()
0x7CFE Jul 9, 2016
eb8eeb9
Refactors inference.h by namespaces by adding explicit st:: prefix
0x7CFE Jul 9, 2016
40eb706
Adds initial inference logic to the MethodCompiler and JitRuntime
0x7CFE Jul 9, 2016
c6385ad
Context and tempo are now stack allocated, SendBinary partly uses inf…
0x7CFE Jul 10, 2016
3fc7659
Fixes shouldProtectProducer(), variable names and comments
0x7CFE Jul 10, 2016
cc2e736
ControlGraph::TMetaInfo::readsArguments now stores indices of accesse…
0x7CFE Jul 17, 2016
f2c78e3
Adds Type::isBlock()
0x7CFE Jul 17, 2016
cf7d822
Refactors JIT caches to support method/block specialization
0x7CFE Jul 17, 2016
9d39182
Adds support for direct calls of inferred blocks
0x7CFE Jul 17, 2016
5263fe0
Adds nounwind specifier to core helper functions
0x7CFE Jul 17, 2016
c9af814
Adds MethodCompiler::insertTrace() for JIT code trace injection
0x7CFE Jul 17, 2016
15a7e2a
Fixes Type::toString()
0x7CFE Jul 17, 2016
3daecdb
Fixes compiler and runtime related to dynamic block dispatch
0x7CFE Jul 17, 2016
f17ef79
Various fixes of method compiler, control graph and type analyzer
0x7CFE Jul 21, 2016
ee7d469
Adds special handling of dynamically inferred blocks
0x7CFE Jul 21, 2016
a532ac0
Adds TypeSystem::findBlockContext()
0x7CFE Jul 21, 2016
9741b46
Fixes sendToSuper
0x7CFE Jul 21, 2016
206db1c
Refactors JITRuntime::printStat()
0x7CFE Jul 21, 2016
33f4452
Folds argument types of SendBinary instruction
0x7CFE Jul 25, 2016
fc6d1dd
Fixes primitives inference
0x7CFE Jul 25, 2016
878db08
Fixes PushBlock in nested block context
0x7CFE Aug 2, 2016
6a1167e
Adds closure mask for dynamic blocks created in soft VM
0x7CFE Aug 6, 2016
aefcc90
Fixes H_VMImage to test VM primitives
kpp Aug 12, 2016
63f134e
Frees mem in TypeSystem
kpp Aug 13, 2016
62019e7
Fixes case 2 & (SmallInt) -> (SmallInt)
kpp Aug 13, 2016
033a3e8
Fixes automkdir for graphviz
kpp Aug 13, 2016
34c1048
Adds basic tests and patterns for type inference
kpp Aug 12, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ add_library(stapi
src/ParsedBlock.cpp

src/ControlGraph.cpp
src/TauLinker.cpp
src/ControlGraphVisualizer.cpp
src/TypeAnalyzer.cpp
)

set(MM_CPP_FILES
Expand Down
97 changes: 93 additions & 4 deletions doc/types.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
id: param
^param

Ти́повое выражение:
Т́иповое выражение:
self::*, param::* -> self, param


Expand All @@ -26,13 +26,13 @@
^ a + b

Контекст object sum: intvara and: intvarb
self::*, (SmallInt), (SmallInt) -> self, (SmallInt)
self::*, a::(SmallInt), b::(SmallInt) -> self', (SmallInt)

Контекст object sum: 2 and: 3
self::*, a::2, b::3 -> self, 5

Обобщенный метод
self::*, a::*, b::* -> self'::*, *
self::*, a::*, b::* -> self', *

то есть, литеральные значения протаскиваются прямо через тип

Expand Down Expand Up @@ -72,9 +72,10 @@
Контекст object dirty: 42
self::[_,_,_], param::42 -> self'::[_,_,42], 43

Примечание: в случае утекания self, мы не можем утверждать, что self' будет таким. Придется фолбечиться на self'::*


А теперь самый вынос мозга — система контекста виртуальной машине — это монод в категории эндофункторов! Монада то бишь.
А теперь самый вынос мозга — система контекста виртуальной машине — это моноид в категории эндофункторов! Монада то бишь.
Переход виртуальной машины от одного состояния к другому — это монадическая операция.

А это внезапно означает:
Expand Down Expand Up @@ -106,6 +107,7 @@
Монадические отношения в связи с объектом self позволяют формализовать тот факт, что при вызове метода поля самого объекта не меняются.
Это позволяет более смело выполнять оптимизации и связывать далекие участки графа без опасения что типы совпали «случайно».

Поправка — нихрена :( Если self утек в другой объект, то вызывая методы он может поменять и нас. Только при инлайнинге и доказательсве.


Типы методов:
Expand Down Expand Up @@ -184,3 +186,90 @@
Впрочем, ветви кэша кодируются как вызовы специализированных версий методов,
поскольку в пределах ветви класс отправителя (self) становится известен.


Блоки, акт второй.

Классификация блоков относительно типов
ContextFree [ 42 ], [ :x | x + 1 ], [ :x :y | x < y ]
ContextAccessor [ x message ], [ x + 1 ], [ anArgument message: aTemporary ]
ContextMutator [ x <- nil ], [ :x | sum <- sum + x ]

BlockReturn [ ^42 ]

Классификация точки вызова блоков
Never
Once y <- [ :x | x ] value: 42
Maybe <Never + Once>
Multi 1 to: 10 do: [ :x | sum <- sum + x ]
Escape *::anObject take: (Block)::aBlock


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

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

Never
Блок не учитывается в выводе типов

Once
Блок подключается параллельно инструкции, принимающей его параметром, например 1 to: 10: do: [ ... ]

Maybe
То же, что и для Once, но есть параллельное ребро мимо блока

Multi
То же, что и Multi, но еще добавляется возвратное ребро в начало блока

Escape
Вызовы этого типа не могут быть представлены в виде графа и блокируют вывод типов для задействованных переменных

После построения inline графа, выполняется проход TauLinker-а на нем,
полученные тау узлы могут быть использованы для вывода типов переменных.


Итак, алгоритм.

Для метода, в лексическом контексте которого объявляется блок:
1. Получаем список переменных, которые мутирует блок (известно после анализа графа блока)
2. Выполняем анализ для каждой посылки, которая использует блок как параметр
3. В точку вызова передаем тип всех временных переменных, используемых блоком (как аргументы)
4. После анализа посылки изучаем контекст на предмет поменявшихся типов переменных
5. Если тип поменялся, то маркируем текущую посылку как мутатор
6. После маркировки всех мутаторов обновляем тау узлы графа и точки их использования
7. Пересчитываем все заново с обновленным графом (новых мутаторов добавиться не должно)

Для метода, принимающего литеральный блок параметром:
1. В каждой посылке, использующей переданный аргументом блок выполняем анализ «как есть»
2. Аккумулируем типы меняющихся переменных
3. Возвращаем аккумулированный результат

Для методов Block>>value* (код обработчика примитива 8)
1. Проводим анализ блока, передав типы аргументов и переменных
2. Получаем типы переменных и результата
3. Возвращаем все добро наверх


Проходы анализатора, в зависимости от типа метода:
1. Метод, не содержащий ветвлений доказывается за 1 проход
2. Метод, с литеральными условиями при ветвлениях доказывается за 1 проход
3. Метод, не содержащий циклов (обратных ребер) доказывается за 1 проход
4. Метод, содержащий циклы, но не имеющий тау узлов с обратными ребрами, доказывается за 1? проход
5. Метод, содержащий циклы и имеющий циклическую зависимость по данным (x <- x + 1), доказывается за 2 прохода

6. Метод, содержащий литеральные блоки, вне циклов: если нет замыканий или только читают — 1 проход, если пишут — минимум 2 прохода
7. Метод, содержащий литеральные блоки, в циклах — минимум 3 прохода
8. Метод, содержащий литеральные блоки, записанные в переменную

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

9. Метод, содержащий литеральные блоки, утекающие в неизвестность — полная блокировка вывода переменных, которые они пишут


Алгоритм анализатора:
1. Делаем базовый проход без обратных ребер
2. Если предыдущий проход вывел возврат по литеральному пути и метод не содержит блоков мутаторов — выход
3. Делаем базовый проход с нетривиальными мутаторами
4. Если есть литеральный возврат — выход
5. Делаем индукционный переход

Loading