Skip to content

Commit 04016dc

Browse files
committed
[GR-30514] Use Env#parseInternal for parsing
PullRequest: truffleruby/2549
2 parents c4303bb + bc54e9b commit 04016dc

33 files changed

+316
-236
lines changed

src/main/java/org/truffleruby/RubyContext.java

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@
8484
import org.truffleruby.shared.TruffleRuby;
8585
import org.truffleruby.shared.options.OptionsCatalog;
8686
import org.truffleruby.shared.options.RubyOptionTypes;
87-
import org.truffleruby.stdlib.CoverageManager;
8887
import org.truffleruby.stdlib.readline.ConsoleHolder;
8988

9089
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
@@ -112,7 +111,7 @@ public class RubyContext {
112111

113112
private final SafepointManager safepointManager;
114113
private final InteropManager interopManager = new InteropManager(this);
115-
private final CodeLoader codeLoader = new CodeLoader(this);
114+
private final CodeLoader codeLoader;
116115
private final FeatureLoader featureLoader;
117116
private final TraceManager traceManager;
118117
private final ReferenceProcessor referenceProcessor;
@@ -143,7 +142,6 @@ public class RubyContext {
143142
@CompilationFinal private CoreMethods coreMethods;
144143
private final ThreadManager threadManager;
145144
private final LexicalScope rootLexicalScope;
146-
private final CoverageManager coverageManager;
147145
private volatile ConsoleHolder consoleHolder;
148146

149147
public final ContextArray<GlobalVariableStorage> globalVariablesArray;
@@ -179,6 +177,7 @@ public RubyContext(RubyLanguage language, TruffleLanguage.Env env) {
179177
coreExceptions = new CoreExceptions(this, language);
180178
encodingManager = new EncodingManager(this, language);
181179

180+
codeLoader = new CodeLoader(language, this);
182181
featureLoader = new FeatureLoader(this, language);
183182
referenceProcessor = new ReferenceProcessor(this);
184183
finalizationService = new FinalizationService(this, referenceProcessor);
@@ -230,7 +229,6 @@ public RubyContext(RubyLanguage language, TruffleLanguage.Env env) {
230229
Metrics.printTime("before-instruments");
231230
final Instrumenter instrumenter = env.lookup(Instrumenter.class);
232231
traceManager = new TraceManager(language, this, instrumenter);
233-
coverageManager = new CoverageManager(this, instrumenter);
234232
Metrics.printTime("after-instruments");
235233

236234
Metrics.printTime("after-context-constructor");
@@ -526,10 +524,6 @@ private void dispose() {
526524
RubyLanguage.LOGGER.info(
527525
"Total VALUE object to native conversions: " + getValueWrapperManager().totalHandleAllocations());
528526
}
529-
530-
if (options.COVERAGE_GLOBAL) {
531-
coverageManager.print(this, System.out);
532-
}
533527
}
534528

535529
public boolean isPreInitializing() {
@@ -632,10 +626,6 @@ public LexicalScope getRootLexicalScope() {
632626
return rootLexicalScope;
633627
}
634628

635-
public CoverageManager getCoverageManager() {
636-
return coverageManager;
637-
}
638-
639629
public CodeLoader getCodeLoader() {
640630
return codeLoader;
641631
}

src/main/java/org/truffleruby/RubyFileTypeDetector.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import org.truffleruby.core.rope.Rope;
2323
import org.truffleruby.core.string.StringOperations;
2424
import org.truffleruby.parser.lexer.RubyLexer;
25-
import org.truffleruby.shared.TruffleRuby;
2625

2726
import com.oracle.truffle.api.TruffleFile;
2827

@@ -44,20 +43,20 @@ public String findMimeType(TruffleFile file) throws IOException {
4443

4544
for (String candidate : KNOWN_RUBY_SUFFIXES) {
4645
if (lowerCaseFileName.endsWith(candidate)) {
47-
return TruffleRuby.MIME_TYPE;
46+
return RubyLanguage.getMimeType(false);
4847
}
4948
}
5049

5150
for (String candidate : KNOWN_RUBY_FILES) {
5251
if (fileName.equals(candidate)) {
53-
return TruffleRuby.MIME_TYPE;
52+
return RubyLanguage.getMimeType(false);
5453
}
5554
}
5655

5756
try (BufferedReader fileContent = file.newBufferedReader(StandardCharsets.UTF_8)) {
5857
final String firstLine = fileContent.readLine();
5958
if (firstLine != null && SHEBANG_REGEXP.matcher(firstLine).matches()) {
60-
return TruffleRuby.MIME_TYPE;
59+
return RubyLanguage.getMimeType(false);
6160
}
6261
} catch (IOException | SecurityException e) {
6362
// Reading random files as UTF-8 could cause all sorts of errors

src/main/java/org/truffleruby/RubyLanguage.java

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.oracle.truffle.api.CompilerAsserts;
2121
import com.oracle.truffle.api.CompilerDirectives;
2222
import com.oracle.truffle.api.instrumentation.AllocationReporter;
23+
import com.oracle.truffle.api.instrumentation.Instrumenter;
2324
import com.oracle.truffle.api.object.Shape;
2425
import com.oracle.truffle.api.source.Source;
2526
import com.oracle.truffle.api.source.SourceSection;
@@ -93,6 +94,9 @@
9394
import org.truffleruby.language.objects.RubyObjectType;
9495
import org.truffleruby.language.objects.classvariables.ClassVariableStorage;
9596
import org.truffleruby.options.LanguageOptions;
97+
import org.truffleruby.parser.ParserContext;
98+
import org.truffleruby.parser.ParsingParameters;
99+
import org.truffleruby.parser.RubySource;
96100
import org.truffleruby.platform.Platform;
97101
import org.truffleruby.shared.Metrics;
98102
import org.truffleruby.shared.TruffleRuby;
@@ -119,8 +123,11 @@
119123
id = TruffleRuby.LANGUAGE_ID,
120124
implementationName = TruffleRuby.FORMAL_NAME,
121125
version = TruffleRuby.LANGUAGE_VERSION,
122-
characterMimeTypes = TruffleRuby.MIME_TYPE,
123-
defaultMimeType = TruffleRuby.MIME_TYPE,
126+
characterMimeTypes = {
127+
RubyLanguage.MIME_TYPE,
128+
RubyLanguage.MIME_TYPE_COVERAGE,
129+
RubyLanguage.MIME_TYPE_MAIN_SCRIPT },
130+
defaultMimeType = RubyLanguage.MIME_TYPE,
124131
dependentLanguages = { "nfi", "llvm", "regex" },
125132
fileTypeDetectors = RubyFileTypeDetector.class)
126133
@ProvidedTags({
@@ -136,6 +143,12 @@
136143
})
137144
public final class RubyLanguage extends TruffleLanguage<RubyContext> {
138145

146+
/** Do not access directly, instead use {@link #getMimeType(boolean)} */
147+
static final String MIME_TYPE = "application/x-ruby";
148+
public static final String MIME_TYPE_COVERAGE = "application/x-ruby;coverage=true";
149+
public static final String MIME_TYPE_MAIN_SCRIPT = "application/x-ruby;main-script=true";
150+
public static final String[] MIME_TYPES = { MIME_TYPE, MIME_TYPE_COVERAGE, MIME_TYPE_MAIN_SCRIPT };
151+
139152
public static final String PLATFORM = String.format(
140153
"%s-%s%s",
141154
Platform.getArchName(),
@@ -176,6 +189,7 @@ public final class RubyLanguage extends TruffleLanguage<RubyContext> {
176189
@CompilationFinal public LanguageOptions options;
177190

178191
@CompilationFinal private AllocationReporter allocationReporter;
192+
@CompilationFinal public CoverageManager coverageManager;
179193

180194
private final AtomicLong nextObjectID = new AtomicLong(ObjectSpaceManager.INITIAL_LANGUAGE_OBJECT_ID);
181195
private final PathToRopeCache pathToRopeCache = new PathToRopeCache(this);
@@ -238,6 +252,8 @@ public final class RubyLanguage extends TruffleLanguage<RubyContext> {
238252
.layout(ClassVariableStorage.class)
239253
.build();
240254

255+
public final ThreadLocal<ParsingParameters> parsingRequestParams = new ThreadLocal<>();
256+
241257
public RubyLanguage() {
242258
coreMethodAssumptions = new CoreMethodAssumptions(this);
243259
coreStrings = new CoreStrings(this);
@@ -249,6 +265,10 @@ public RubyLanguage() {
249265
encodings = new Encodings(this);
250266
}
251267

268+
public static String getMimeType(boolean coverageEnabled) {
269+
return coverageEnabled ? MIME_TYPE_COVERAGE : MIME_TYPE;
270+
}
271+
252272
@TruffleBoundary
253273
public static String fileLine(SourceSection section) {
254274
if (section == null) {
@@ -333,13 +353,12 @@ public RubyContext createContext(Env env) {
333353
Metrics.initializeOption();
334354

335355
synchronized (this) {
336-
if (allocationReporter == null) {
337-
allocationReporter = env.lookup(AllocationReporter.class);
338-
}
339-
if (this.options == null) {
356+
if (this.options == null) { // First context
357+
this.allocationReporter = env.lookup(AllocationReporter.class);
340358
this.options = new LanguageOptions(env, env.getOptions(), singleContext);
341359
this.coreLoadPath = buildCoreLoadPath(this.options.CORE_LOAD_PATH);
342360
this.corePath = coreLoadPath + File.separator + "core" + File.separator;
361+
this.coverageManager = new CoverageManager(options, env.lookup(Instrumenter.class));
343362
primitiveManager.loadCoreMethodNodes(this.options);
344363
}
345364
}
@@ -408,6 +427,10 @@ protected void finalizeContext(RubyContext context) {
408427
protected void disposeContext(RubyContext context) {
409428
LOGGER.fine("disposeContext()");
410429
context.disposeContext();
430+
431+
if (options.COVERAGE_GLOBAL) {
432+
coverageManager.print(this, System.out);
433+
}
411434
}
412435

413436
public static RubyContext getCurrentContext() {
@@ -422,15 +445,36 @@ public static RubyLanguage getCurrentLanguage() {
422445

423446
@Override
424447
protected RootCallTarget parse(ParsingRequest request) {
425-
if (request.getSource().isInteractive()) {
426-
return Truffle.getRuntime().createCallTarget(new RubyEvalInteractiveRootNode(this, request.getSource()));
448+
final Source source = request.getSource();
449+
450+
final ParsingParameters parsingParameters = parsingRequestParams.get();
451+
if (parsingParameters != null) { // from #require or core library
452+
assert parsingParameters.getSource().equals(source);
453+
final RubySource rubySource = new RubySource(
454+
source,
455+
parsingParameters.getPath(),
456+
parsingParameters.getRope());
457+
final ParserContext parserContext = MIME_TYPE_MAIN_SCRIPT.equals(source.getMimeType())
458+
? ParserContext.TOP_LEVEL_FIRST
459+
: ParserContext.TOP_LEVEL;
460+
return RubyLanguage.getCurrentContext().getCodeLoader().parse(
461+
rubySource,
462+
parserContext,
463+
null,
464+
null,
465+
true,
466+
parsingParameters.getCurrentNode());
467+
}
468+
469+
if (source.isInteractive()) {
470+
return Truffle.getRuntime().createCallTarget(new RubyEvalInteractiveRootNode(this, source));
427471
} else {
428472
final RubyContext context = Objects.requireNonNull(getCurrentContext());
429473
return Truffle.getRuntime().createCallTarget(
430474
new RubyParsingRequestNode(
431475
this,
432476
context,
433-
request.getSource(),
477+
source,
434478
request.getArgumentNames().toArray(StringUtils.EMPTY_STRING_ARRAY)));
435479
}
436480
}

src/main/java/org/truffleruby/aot/ParserCache.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import java.util.stream.Collectors;
1616

1717
import com.oracle.truffle.api.CompilerDirectives;
18+
import com.oracle.truffle.api.source.Source;
1819
import org.truffleruby.core.CoreLibrary;
1920
import org.truffleruby.language.loader.ResourceLoader;
2021
import org.truffleruby.parser.RubyDeferredWarnings;
@@ -51,8 +52,9 @@ public class ParserCache {
5152

5253
private static RubySource loadSource(String feature) {
5354
try {
54-
final ResourceLoader resourceLoader = new ResourceLoader();
55-
return resourceLoader.loadResource(feature, OptionsCatalog.CORE_AS_INTERNAL_KEY.getDefaultValue());
55+
final Source source = ResourceLoader
56+
.loadResource(feature, OptionsCatalog.CORE_AS_INTERNAL_KEY.getDefaultValue());
57+
return new RubySource(source, feature);
5658
} catch (IOException e) {
5759
throw CompilerDirectives.shouldNotReachHere(e);
5860
}

src/main/java/org/truffleruby/core/CoreLibrary.java

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import java.util.concurrent.ConcurrentHashMap;
2323
import java.util.concurrent.ConcurrentMap;
2424

25+
import com.oracle.truffle.api.RootCallTarget;
26+
import org.graalvm.collections.Pair;
2527
import org.jcodings.specific.USASCIIEncoding;
2628
import org.jcodings.transcode.EConvFlags;
2729
import org.truffleruby.Layouts;
@@ -42,6 +44,7 @@
4244
import org.truffleruby.core.numeric.BigIntegerOps;
4345
import org.truffleruby.core.numeric.RubyBignum;
4446
import org.truffleruby.core.rope.CodeRange;
47+
import org.truffleruby.core.rope.Rope;
4548
import org.truffleruby.core.string.RubyString;
4649
import org.truffleruby.core.string.StringOperations;
4750
import org.truffleruby.debug.BindingLocalVariablesObject;
@@ -51,7 +54,6 @@
5154
import org.truffleruby.core.string.ImmutableRubyString;
5255
import org.truffleruby.language.Nil;
5356
import org.truffleruby.language.NotProvided;
54-
import org.truffleruby.language.RubyRootNode;
5557
import org.truffleruby.language.control.RaiseException;
5658
import org.truffleruby.language.globals.GlobalVariableReader;
5759
import org.truffleruby.language.globals.GlobalVariables;
@@ -63,7 +65,6 @@
6365
import org.truffleruby.language.methods.SharedMethodInfo;
6466
import org.truffleruby.language.objects.SingletonClassNode;
6567
import org.truffleruby.parser.ParserContext;
66-
import org.truffleruby.parser.RubySource;
6768
import org.truffleruby.parser.TranslatorDriver;
6869
import org.truffleruby.parser.ast.RootParseNode;
6970
import org.truffleruby.platform.NativeConfiguration;
@@ -754,28 +755,26 @@ public void loadRubyCoreLibraryAndPostBoot() {
754755
state = State.LOADING_RUBY_CORE;
755756

756757
try {
757-
for (int n = 0; n < CORE_FILES.length; n++) {
758-
final String file = CORE_FILES[n];
758+
for (String file : CORE_FILES) {
759759
if (file == POST_BOOT_FILE) {
760760
afterLoadCoreLibrary();
761761
state = State.LOADED;
762762
}
763763

764-
final RubySource source = loadCoreFile(language.coreLoadPath + file);
765-
final RubyRootNode rootNode = context
766-
.getCodeLoader()
767-
.parse(source, ParserContext.TOP_LEVEL, null, null, true, node);
764+
final Pair<Source, Rope> sourceRopePair = loadCoreFileSource(language.coreLoadPath + file);
765+
final Source source = sourceRopePair.getLeft();
766+
final RootCallTarget callTarget = context.getCodeLoader().parseTopLevelWithCache(sourceRopePair, node);
768767

769768
final CodeLoader.DeferredCall deferredCall = context.getCodeLoader().prepareExecute(
769+
callTarget,
770770
ParserContext.TOP_LEVEL,
771771
DeclarationContext.topLevel(context),
772-
rootNode,
773772
null,
774773
context.getCoreLibrary().mainObject);
775774

776-
TranslatorDriver.printParseTranslateExecuteMetric("before-execute", context, source.getSource());
775+
TranslatorDriver.printParseTranslateExecuteMetric("before-execute", context, source);
777776
deferredCall.callWithoutCallNode();
778-
TranslatorDriver.printParseTranslateExecuteMetric("after-execute", context, source.getSource());
777+
TranslatorDriver.printParseTranslateExecuteMetric("after-execute", context, source);
779778
}
780779
} catch (IOException e) {
781780
throw CompilerDirectives.shouldNotReachHere(e);
@@ -787,18 +786,17 @@ public void loadRubyCoreLibraryAndPostBoot() {
787786
}
788787
}
789788

790-
public RubySource loadCoreFile(String path) throws IOException {
789+
public Pair<Source, Rope> loadCoreFileSource(String path) throws IOException {
791790
if (path.startsWith(RubyLanguage.RESOURCE_SCHEME)) {
792791
if (TruffleOptions.AOT || ParserCache.INSTANCE != null) {
793792
final RootParseNode rootParseNode = ParserCache.INSTANCE.get(path);
794-
return new RubySource(rootParseNode.getSource(), path);
793+
return Pair.create(rootParseNode.getSource(), null);
795794
} else {
796-
final ResourceLoader resourceLoader = new ResourceLoader();
797-
return resourceLoader.loadResource(path, language.options.CORE_AS_INTERNAL);
795+
return Pair.create(ResourceLoader.loadResource(path, language.options.CORE_AS_INTERNAL), null);
798796
}
799797
} else {
800798
final FileLoader fileLoader = new FileLoader(context, language);
801-
return fileLoader.loadFile(context.getEnv(), path);
799+
return fileLoader.loadFile(path);
802800
}
803801
}
804802

src/main/java/org/truffleruby/core/basicobject/BasicObjectNodes.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
import org.truffleruby.language.RubyDynamicObject;
4646
import org.truffleruby.language.RubyGuards;
4747
import org.truffleruby.language.RubyNode;
48-
import org.truffleruby.language.RubyRootNode;
4948
import org.truffleruby.language.RubySourceNode;
5049
import org.truffleruby.language.Visibility;
5150
import org.truffleruby.language.arguments.ReadCallerFrameNode;
@@ -396,7 +395,7 @@ private Object instanceEvalHelper(MaterializedFrame callerFrame, Object receiver
396395
final RubySource source = createEvalSourceNode
397396
.createEvalSource(stringRope, "instance_eval", fileNameString, line);
398397

399-
final RubyRootNode rootNode = getContext().getCodeLoader().parse(
398+
final RootCallTarget callTarget = getContext().getCodeLoader().parse(
400399
source,
401400
ParserContext.EVAL,
402401
callerFrame,
@@ -410,9 +409,9 @@ private Object instanceEvalHelper(MaterializedFrame callerFrame, Object receiver
410409
DeclarationContext.NO_REFINEMENTS);
411410

412411
final CodeLoader.DeferredCall deferredCall = getContext().getCodeLoader().prepareExecute(
412+
callTarget,
413413
ParserContext.EVAL,
414414
declarationContext,
415-
rootNode,
416415
callerFrame,
417416
receiver);
418417

0 commit comments

Comments
 (0)