Skip to content

Commit f2d41fb

Browse files
raph-amiardHugoGGuerrier
authored andcommitted
Perf: lazily compute all/specified units in LKQLContext
1 parent 6869a15 commit f2d41fb

File tree

3 files changed

+30
-78
lines changed

3 files changed

+30
-78
lines changed

lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLContext.java

Lines changed: 17 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.io.File;
2727
import java.util.*;
2828
import java.util.function.BiConsumer;
29+
import java.util.stream.Stream;
2930
import org.json.JSONObject;
3031
import org.json.JSONTokener;
3132

@@ -94,21 +95,6 @@ public final class LKQLContext {
9495
*/
9596
private List<String> allSourceFiles;
9697

97-
/** Whether the source files were parsed. */
98-
private boolean parsed;
99-
100-
/**
101-
* The user-specified units to analyze. If not explicitly specified, those will be the units of
102-
* the root project.
103-
*/
104-
private LangkitSupport.AnalysisUnit[] specifiedUnits;
105-
106-
/** All the units of the project, including those of its non-externally-built dependencies. */
107-
private LangkitSupport.AnalysisUnit[] allUnits;
108-
109-
/** The root nodes of all the analysis units of the project. */
110-
private LangkitSupport.NodeInterface[] allUnitsRoots;
111-
11298
// ----- Checker attributes -----
11399

114100
/** A cache for all rule arguments to avoid evaluating twice the same argument source. */
@@ -160,7 +146,6 @@ public LKQLContext(TruffleLanguage.Env env, GlobalScope global, LKQLLanguage lan
160146
this.global = global;
161147
this.specifiedSourceFiles = new ArrayList<>();
162148
this.allSourceFiles = new ArrayList<>();
163-
this.parsed = false;
164149
this.language = language;
165150
}
166151

@@ -186,36 +171,34 @@ public GlobalScope getGlobal() {
186171
return this.global;
187172
}
188173

189-
public LangkitSupport.AnalysisUnit[] getSpecifiedUnits() {
190-
if (!this.parsed) {
191-
this.parseSources();
192-
}
193-
return this.specifiedUnits;
174+
public Stream<LangkitSupport.AnalysisUnit> getSpecifiedUnits() {
175+
String[] ignores = this.getIgnores();
176+
return this.specifiedSourceFiles.stream()
177+
.filter(source -> Arrays.stream(ignores).noneMatch(source::contains))
178+
.map(f -> analysisContext.getUnitFromFile(f));
194179
}
195180

196-
public LangkitSupport.AnalysisUnit[] getAllUnits() {
197-
if (!this.parsed) {
198-
this.parseSources();
199-
}
200-
return this.allUnits;
181+
public Stream<LangkitSupport.AnalysisUnit> getAllUnits() {
182+
String[] ignores = this.getIgnores();
183+
return this.allSourceFiles.stream()
184+
.map(f -> {
185+
return analysisContext.getUnitFromFile(f);
186+
});
201187
}
202188

203-
public LangkitSupport.NodeInterface[] getAllUnitsRoots() {
204-
if (!this.parsed) {
205-
this.parseSources();
206-
}
207-
return this.allUnitsRoots;
189+
@CompilerDirectives.TruffleBoundary
190+
public LangkitSupport.NodeInterface[] allUnitsRoots() {
191+
return getAllUnits().map(u -> u.getRoot()).toArray(LangkitSupport.NodeInterface[]::new);
208192
}
209193

210194
public boolean hasRewritingContext() {
211195
return this.rewritingContext != null;
212196
}
213197

198+
@CompilerDirectives.TruffleBoundary
214199
public LangkitSupport.RewritingContextInterface getRewritingContext() {
215200
if (this.rewritingContext == null) {
216-
if (!this.parsed) {
217-
this.parseSources();
218-
}
201+
var ignore = getAllUnits().toArray(LangkitSupport.AnalysisUnit[]::new);
219202
this.rewritingContext = this.analysisContext.startRewriting();
220203
}
221204
return this.rewritingContext;
@@ -420,52 +403,11 @@ public CheckerUtils.DiagnosticEmitter getDiagnosticEmitter() {
420403
return this.emitter;
421404
}
422405

423-
// ----- Project analysis methods -----
424-
425-
/** Parse the ada source files and store analysis units and root nodes. */
426-
@CompilerDirectives.TruffleBoundary
427-
public void parseSources() {
428-
// Filter the Ada source file list
429-
String[] ignores = this.getIgnores();
430-
String[] usedSources =
431-
this.specifiedSourceFiles.stream()
432-
.filter(source -> {
433-
for (String ignore : ignores) {
434-
if (source.contains(ignore)) return false;
435-
}
436-
return true;
437-
})
438-
.toArray(String[]::new);
439-
440-
// For each specified source file, store its corresponding analysis unit in the list of
441-
// specified units
442-
this.specifiedUnits = new LangkitSupport.AnalysisUnit[usedSources.length];
443-
for (int i = 0; i < usedSources.length; i++) {
444-
this.specifiedUnits[i] = this.analysisContext.getUnitFromFile(usedSources[i]);
445-
}
446-
447-
// For each source file of the project, store its corresponding analysis unit in the list of
448-
// all
449-
// the units
450-
// of the project, as well as their root nodes.
451-
this.allUnits = new LangkitSupport.AnalysisUnit[this.allSourceFiles.size()];
452-
this.allUnitsRoots = new LangkitSupport.NodeInterface[this.allSourceFiles.size()];
453-
454-
for (int i = 0; i < this.allUnits.length; i++) {
455-
this.allUnits[i] = this.analysisContext.getUnitFromFile(this.allSourceFiles.get(i));
456-
this.allUnitsRoots[i] = this.allUnits[i].getRoot();
457-
}
458-
459-
// All source files are now parsed
460-
this.parsed = true;
461-
}
462-
463406
/** Initialize the ada sources. */
464407
public void initSources() {
465408
// Reset the context fields
466409
this.specifiedSourceFiles.clear();
467410
this.allSourceFiles.clear();
468-
this.parsed = false;
469411

470412
// Add all the user-specified files to process after verifying they exist
471413
for (String file : this.getFiles()) {

lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInFunctions.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package com.adacore.lkql_jit.built_ins;
77

8+
import com.adacore.langkit_support.LangkitSupport;
89
import com.adacore.lkql_jit.LKQLLanguage;
910
import com.adacore.lkql_jit.LKQLTypeSystemGen;
1011
import com.adacore.lkql_jit.annotations.*;
@@ -537,17 +538,26 @@ protected Object onLKQLValue(LKQLValue value) {
537538
abstract static class UnitsExpr extends BuiltInBody {
538539

539540
@Specialization
541+
@CompilerDirectives.TruffleBoundary
540542
protected LKQLList alwaysTrue() {
541-
return new LKQLList(LKQLLanguage.getContext(this).getAllUnits());
543+
return new LKQLList(
544+
LKQLLanguage.getContext(this)
545+
.getAllUnits()
546+
.toArray(LangkitSupport.AnalysisUnit[]::new)
547+
);
542548
}
543549
}
544550

545551
@BuiltInFunction(name = "specified_units", doc = "Return a list of units specified by the user")
546552
abstract static class SpecifiedUnitsExpr extends BuiltInBody {
547553

548554
@Specialization
555+
@CompilerDirectives.TruffleBoundary
549556
protected LKQLList alwaysTrue() {
550-
return new LKQLList(LKQLLanguage.getContext(this).getSpecifiedUnits());
557+
var units = LKQLLanguage.getContext(this)
558+
.getSpecifiedUnits()
559+
.toArray(LangkitSupport.AnalysisUnit[]::new);
560+
return new LKQLList(units);
551561
}
552562
}
553563
}

lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ else if (LKQLTypeSystemGen.isLKQLList(fromObject)) {
138138
}
139139
// Else, there is no "from" expression, we get the default roots
140140
else {
141-
fromNodes = LKQLLanguage.getContext(this.pattern).getAllUnitsRoots();
141+
fromNodes = LKQLLanguage.getContext(this.pattern).allUnitsRoots();
142142
}
143143

144144
// If the query mode is all

0 commit comments

Comments
 (0)