Skip to content

Commit 40403e7

Browse files
committed
compiler: refactor build queue
Extract BuildQueue from BlockBuilder and TypeBuilder to get better control over when different classes, functions, etc, are compiled, improving abilities when it comes to lazy compilation.
1 parent 453b4b5 commit 40403e7

15 files changed

+311
-248
lines changed

src/compiler/core/Compiler.cs

+14-10
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public class Compiler : LogObject, ICompiler, IScheduler
4949
public readonly NameResolver NameResolver;
5050

5151
// Building
52+
public readonly BuildQueue Queue;
5253
public readonly BlockBuilder BlockBuilder;
5354
public readonly BundleBuilder BundleBuilder;
5455
public readonly TypeBuilder TypeBuilder;
@@ -91,8 +92,9 @@ public Compiler(Log log, Backend backend, SourceBundle bundle, CompilerOptions o
9192
var data = Data = new BuildData(il, extensions, ilf);
9293
var environment = Environment = new BuildEnvironment(backend, bundle, options, extensions, ilf, this);
9394
var input = Input = new SourceReader(log, bundle, environment);
94-
var blockBuilder = BlockBuilder = new BlockBuilder(backend, il, ilf, resolver, this);
95-
var typeBuilder = TypeBuilder = new TypeBuilder(environment, ilf, resolver, this);
95+
var queue = Queue = new BuildQueue(log, environment, backend, this);
96+
var blockBuilder = BlockBuilder = new BlockBuilder(backend, il, ilf, resolver, this, queue);
97+
var typeBuilder = TypeBuilder = new TypeBuilder(environment, ilf, resolver, this, queue);
9698
BundleBuilder = new BundleBuilder(backend, environment, ilf, this);
9799
AstProcessor = new AstProcessor(il, blockBuilder, typeBuilder, resolver, environment);
98100
UxlProcessor = new UxlProcessor(disk, backend.Name, il, extensions, environment, ilf);
@@ -132,20 +134,23 @@ public void Compile()
132134
if (Backend.CanLink(bundle))
133135
bundle.Flags |= SourceBundleFlags.CanLink;
134136

135-
using (Log.StartProfiler(TypeBuilder))
136-
TypeBuilder.Build();
137+
using (Log.StartProfiler(Queue))
138+
Queue.BuildTypesAndFunctions();
139+
137140
if (Log.HasErrors)
138141
return;
139142

140-
Backend.ShaderBackend.Initialize(this, BundleBuilder);
143+
using (Log.StartProfiler(UxlProcessor))
144+
UxlProcessor.CompileDocuments();
141145

142-
using (Log.StartProfiler(BlockBuilder))
143-
BlockBuilder.Build();
144146
if (Log.HasErrors)
145147
return;
146148

147-
using (Log.StartProfiler(UxlProcessor))
148-
UxlProcessor.CompileDocuments();
149+
Backend.ShaderBackend.Initialize(this, BundleBuilder);
150+
151+
using (Log.StartProfiler(Queue))
152+
Queue.BuildEverything();
153+
149154
if (Log.HasErrors)
150155
return;
151156

@@ -205,7 +210,6 @@ public BackendResult Generate(Action<ICompiler> callback)
205210
UxlProcessor.CompileRequirements();
206211
ILStripper.Begin();
207212
Run(_transforms);
208-
TypeBuilder.BuildTypes();
209213

210214
using (Log.StartProfiler(ILStripper))
211215
ILStripper.End();

src/compiler/core/IL/EntitySwapper.cs

-2
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ DataType GetTypeInternal(DataType dt)
6565
args[i] = GetType(dt.FlattenedArguments[i]);
6666

6767
result = TypeBuilder.Parameterize(result.Source, def, args);
68-
TypeBuilder.BuildTypes();
6968
SwapTypes.Add(dt, result);
7069
return result;
7170
}
@@ -99,7 +98,6 @@ DataType GetTypeInternal(DataType dt)
9998

10099
var def = result.IsGenericDefinition ? result : GetType(dt.GenericDefinition);
101100
result = TypeBuilder.Parameterize(dt.Source, def, args);
102-
TypeBuilder.BuildTypes();
103101
}
104102

105103
SwapTypes.Add(dt, result);

src/compiler/core/Syntax/Builders/BlockBuilder.CompileDraw.cs

+2-4
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,8 @@ public Statement CompileDraw(Function func, List<VariableScope> vscopeStack, Ast
3232

3333
var result = new DrawBlock(draw.Source, parent, method, FlattenVariableScopes(vscopeStack));
3434
method.DrawBlocks.Add(result);
35-
36-
EnqueueBlock(result, x => PopulateBlock(draw.Block, x));
37-
_enqueuedDrawClasses.Add(method.DeclaringType);
38-
35+
_queue.EnqueueBlock(result, x => PopulateBlock(draw.Block, x));
36+
_queue.EnqueueDrawClass(method.DeclaringType);
3937
return result.DrawScope;
4038
}
4139

src/compiler/core/Syntax/Builders/BlockBuilder.CreateBlock.cs

+2-3
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ public Block CreateBlock(AstBlock ast, Namescope parent)
3030
Log.Error(src, ErrorCode.E3214, "Block declaration is not allowed in this scope");
3131

3232
_processedBlocks.Add(ast, result);
33-
EnqueueBlock(result, x => PopulateBlock(ast, x));
34-
33+
_queue.EnqueueBlock(result, x => PopulateBlock(ast, x));
3534
return result;
3635
}
3736

@@ -76,7 +75,7 @@ MetaBlock CreateNodeBlock(AstNode ast, BlockBase parent)
7675
return MetaBlock.Invalid;
7776
}
7877

79-
EnqueueBlock(result, x => PopulateBlock(ast, x));
78+
_queue.EnqueueBlock(result, x => PopulateBlock(ast, x));
8079
return result;
8180
}
8281
}

src/compiler/core/Syntax/Builders/BlockBuilder.CreateMetaProperty.cs

+2-3
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,11 @@ MetaProperty CreateMetaProperty(AstMetaProperty ast, BlockBase parent)
5858
}
5959

6060
var result = new MetaProperty(ast.Name.Source, parent, dt, ast.Name.Symbol, visibility);
61-
_enqueuedProperties.Add(new KeyValuePair<AstMetaProperty, MetaProperty>(ast, result));
62-
61+
_queue.EnqueueMetaProperty(ast, result);
6362
return result;
6463
}
6564

66-
void CompileMetaPropertyDefinitions(AstMetaProperty ast, MetaProperty mp)
65+
internal void CompileMetaPropertyDefinitions(AstMetaProperty ast, MetaProperty mp)
6766
{
6867
var defs = new MetaDefinition[ast.Definitions.Count];
6968

src/compiler/core/Syntax/Builders/BlockBuilder.FlattenType.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public partial class BlockBuilder
88
{
99
internal readonly Dictionary<DataType, HashSet<DataType>> FlattenedTypes = new Dictionary<DataType, HashSet<DataType>>();
1010

11-
void FlattenTypes()
11+
internal void FlattenTypes()
1212
{
1313
FlattenTypes(_il);
1414

src/compiler/core/Syntax/Builders/BlockBuilder.cs

+5-33
Original file line numberDiff line numberDiff line change
@@ -22,54 +22,27 @@ public partial class BlockBuilder : LogObject
2222
readonly ILFactory _ilf;
2323
readonly NameResolver _resolver;
2424
readonly Compiler _compiler;
25+
readonly BuildQueue _queue;
2526
readonly Dictionary<AstBlockBase, Block> _processedBlocks = new Dictionary<AstBlockBase, Block>();
26-
readonly List<BlockBase> _enqueuedBlocks = new List<BlockBase>();
27-
readonly List<KeyValuePair<AstMetaProperty, MetaProperty>> _enqueuedProperties = new List<KeyValuePair<AstMetaProperty, MetaProperty>>();
28-
readonly HashSet<DataType> _enqueuedDrawClasses = new HashSet<DataType>();
2927

3028
Block _terminals;
3129
readonly HashSet<string> _terminalNames = new HashSet<string>();
3230

33-
public BlockBuilder(
31+
internal BlockBuilder(
3432
Backend backend,
3533
Namespace il,
3634
ILFactory ilf,
3735
NameResolver resolver,
38-
Compiler compiler)
36+
Compiler compiler,
37+
BuildQueue queue)
3938
: base(compiler)
4039
{
4140
_backend = backend;
4241
_il = il;
4342
_ilf = ilf;
4443
_resolver = resolver;
4544
_compiler = compiler;
46-
}
47-
48-
void EnqueueBlock(BlockBase b, Action<BlockBase> populate)
49-
{
50-
b.Populating = populate;
51-
_enqueuedBlocks.Add(b);
52-
}
53-
54-
public void Build()
55-
{
56-
FlattenTypes();
57-
58-
for (int i = 0; i < _enqueuedBlocks.Count; i++)
59-
if (!_enqueuedBlocks[i].Source.Bundle.CanLink)
60-
_enqueuedBlocks[i].Populate();
61-
62-
_enqueuedBlocks.Clear();
63-
64-
for (int i = 0; i < _enqueuedProperties.Count; i++)
65-
CompileMetaPropertyDefinitions(_enqueuedProperties[i].Key, _enqueuedProperties[i].Value);
66-
67-
_enqueuedProperties.Clear();
68-
69-
foreach (var dt in _enqueuedDrawClasses)
70-
DrawCallGenerator.GenerateDrawCalls(_compiler, dt);
71-
72-
_enqueuedDrawClasses.Clear();
45+
_queue = queue;
7346
}
7447

7548
public Block TerminalProperties
@@ -83,7 +56,6 @@ public Block TerminalProperties
8356

8457
foreach (var t in _backend.ShaderBackend.InputProperties)
8558
CompileTerminalProperty(t);
86-
8759
foreach (var t in _backend.ShaderBackend.OutputProperties)
8860
CompileTerminalProperty(t);
8961
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Uno.Compiler.API.Backends;
4+
using Uno.Compiler.API.Domain.AST.Members;
5+
using Uno.Compiler.API.Domain.AST.Statements;
6+
using Uno.Compiler.API.Domain.Graphics;
7+
using Uno.Compiler.API.Domain.IL;
8+
using Uno.Compiler.API.Domain.IL.Members;
9+
using Uno.Compiler.Core.Syntax.Compilers;
10+
using Uno.Compiler.Core.Syntax.Generators;
11+
using Uno.Logging;
12+
13+
namespace Uno.Compiler.Core.Syntax.Builders
14+
{
15+
public class BuildQueue : LogObject
16+
{
17+
readonly BuildEnvironment _env;
18+
readonly Backend _backend;
19+
readonly Compiler _compiler;
20+
readonly List<BlockBase> _enqueuedBlocks = new List<BlockBase>();
21+
readonly List<KeyValuePair<AstMetaProperty, MetaProperty>> _enqueuedMetaProperties = new List<KeyValuePair<AstMetaProperty, MetaProperty>>();
22+
readonly HashSet<DataType> _enqueuedDrawClasses = new HashSet<DataType>();
23+
readonly List<FunctionCompiler> _enqueuedFunctions = new List<FunctionCompiler>();
24+
readonly List<Entity> _enqueuedAttributes = new List<Entity>();
25+
readonly List<DataType> _enqueuedTypes = new List<DataType>();
26+
readonly List<Action> _enqueuedActions = new List<Action>();
27+
int _assignBaseTypeIndex;
28+
int _populateMembersIndex;
29+
30+
public BuildQueue(Log log, BuildEnvironment env, Backend backend, Compiler compiler)
31+
: base(log)
32+
{
33+
_env = env;
34+
_backend = backend;
35+
_compiler = compiler;
36+
}
37+
38+
internal FunctionCompiler EnqueueFunction(Function func, DataType parameterizedParent, AstScope body)
39+
{
40+
var fc = new FunctionCompiler(_compiler, func, parameterizedParent, body);
41+
func.Tag = fc;
42+
43+
if (_env.IsGeneratingCode)
44+
func.Stats |= EntityStats.CanLink;
45+
else if (body != null)
46+
_enqueuedFunctions.Add(fc);
47+
else if (_compiler.Backend.CanLink(func))
48+
func.Stats |= EntityStats.CanLink;
49+
50+
return fc;
51+
}
52+
53+
internal void EnqueueDrawClass(DataType declaringType)
54+
{
55+
_enqueuedDrawClasses.Add(declaringType);
56+
}
57+
58+
internal void EnqueueType(DataType dt, Action<DataType> assignBaseType, Action<DataType> populate)
59+
{
60+
if (_env.IsGeneratingCode)
61+
{
62+
assignBaseType(dt);
63+
populate(dt);
64+
return;
65+
}
66+
67+
dt.AssigningBaseType = assignBaseType;
68+
dt.PopulatingMembers = x =>
69+
{
70+
populate(x);
71+
x.Stats &= ~EntityStats.PopulatingMembers;
72+
};
73+
dt.Stats |= EntityStats.PopulatingMembers;
74+
_enqueuedTypes.Add(dt);
75+
}
76+
77+
internal void EnqueueAttributes(Entity e, Action<Entity> assign)
78+
{
79+
e.AssigningAttributes = assign;
80+
_enqueuedAttributes.Add(e);
81+
}
82+
83+
internal void EnqueueAttributes(Member e, DataType parameterizedParent, IReadOnlyList<AstAttribute> attributes)
84+
{
85+
if (attributes.Count > 0)
86+
EnqueueAttributes(e, x => e.SetAttributes(_compiler.CompileAttributes(parameterizedParent, attributes)));
87+
}
88+
89+
public void BuildTypes()
90+
{
91+
for (int count = 0, j = 0; count != _enqueuedTypes.Count && j < 10; j++)
92+
{
93+
count = _enqueuedTypes.Count;
94+
95+
while (_assignBaseTypeIndex < count)
96+
_enqueuedTypes[_assignBaseTypeIndex++].AssignBaseType();
97+
98+
for (int i = 0; i < _enqueuedAttributes.Count; i++)
99+
_enqueuedAttributes[i].AssignAttributes();
100+
101+
_enqueuedAttributes.Clear();
102+
103+
while (_populateMembersIndex < count)
104+
if (_backend.CanLink(_enqueuedTypes[_populateMembersIndex]))
105+
_enqueuedTypes[_populateMembersIndex++].Stats |= EntityStats.CanLink;
106+
else
107+
_enqueuedTypes[_populateMembersIndex++].PopulateMembers();
108+
109+
for (int i = 0; i < _enqueuedActions.Count; i++)
110+
_enqueuedActions[i]();
111+
112+
_enqueuedActions.Clear();
113+
}
114+
115+
for (; _populateMembersIndex < _enqueuedTypes.Count; _populateMembersIndex++)
116+
Log.Warning(_enqueuedTypes[_populateMembersIndex].Source, ErrorCode.I0000, "Unable to parameterize " + _enqueuedTypes[_populateMembersIndex].Quote());
117+
118+
_assignBaseTypeIndex = _populateMembersIndex;
119+
}
120+
121+
public void BuildTypesAndFunctions()
122+
{
123+
BuildTypes();
124+
125+
for (var i = 0; i < _enqueuedFunctions.Count; i++)
126+
{
127+
_enqueuedFunctions[i].Compile();
128+
BuildTypes();
129+
}
130+
131+
_enqueuedFunctions.Clear();
132+
_enqueuedTypes.Clear();
133+
134+
_assignBaseTypeIndex = 0;
135+
_populateMembersIndex = 0;
136+
}
137+
138+
public void BuildEverything()
139+
{
140+
_compiler.BlockBuilder.FlattenTypes();
141+
142+
do
143+
{
144+
BuildTypesAndFunctions();
145+
BuildBlocks();
146+
BuildMetaProperties();
147+
148+
foreach (var dt in _enqueuedDrawClasses)
149+
DrawCallGenerator.GenerateDrawCalls(_compiler, dt);
150+
151+
_enqueuedDrawClasses.Clear();
152+
153+
} while (_enqueuedFunctions.Count > 0);
154+
}
155+
156+
public void BuildBlocks()
157+
{
158+
for (var i = 0; i < _enqueuedBlocks.Count; i++)
159+
if (!_enqueuedBlocks[i].Source.Bundle.CanLink)
160+
_enqueuedBlocks[i].Populate();
161+
162+
_enqueuedBlocks.Clear();
163+
}
164+
165+
internal void EnqueueBlock(BlockBase b, Action<BlockBase> populate)
166+
{
167+
b.Populating = populate;
168+
_enqueuedBlocks.Add(b);
169+
}
170+
171+
public void BuildMetaProperties()
172+
{
173+
for (var i = 0; i < _enqueuedMetaProperties.Count; i++)
174+
_compiler.BlockBuilder.CompileMetaPropertyDefinitions(_enqueuedMetaProperties[i].Key, _enqueuedMetaProperties[i].Value);
175+
176+
_enqueuedMetaProperties.Clear();
177+
}
178+
179+
public void EnqueueMetaProperty(AstMetaProperty ast, MetaProperty result)
180+
{
181+
_enqueuedMetaProperties.Add(new KeyValuePair<AstMetaProperty, MetaProperty>(ast, result));
182+
}
183+
184+
internal void Enqueue(Action action)
185+
{
186+
_enqueuedActions.Add(action);
187+
}
188+
}
189+
}

0 commit comments

Comments
 (0)