Skip to content

Commit

Permalink
[GR-45043] ParserCache does not always have a RubyLanguage
Browse files Browse the repository at this point in the history
PullRequest: truffleruby/4152
  • Loading branch information
eregon committed Feb 5, 2024
2 parents 61cf24b + 0a23e68 commit 610cea3
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 37 deletions.
11 changes: 11 additions & 0 deletions src/main/java/org/truffleruby/RubyLanguage.java
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,17 @@ public String getSourcePath(Source source) {
}
}

@TruffleBoundary
public static String getCorePath(Source source) {
final String path = getPath(source);
String coreLoadPath = OptionsCatalog.CORE_LOAD_PATH_KEY.getDefaultValue();
if (path.startsWith(coreLoadPath)) {
return "<internal:core> " + path.substring(coreLoadPath.length() + 1);
} else {
throw CompilerDirectives.shouldNotReachHere(path + " is not a core path starting with " + coreLoadPath);
}
}

/** Only use when no language/context is available (e.g. Node#toString). Prefer
* {@link RubyContext#fileLine(SourceSection)} as it accounts for coreLoadPath and line offsets. */
@TruffleBoundary
Expand Down
13 changes: 5 additions & 8 deletions src/main/java/org/truffleruby/aot/ParserCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
import org.truffleruby.RubyLanguage;
import org.truffleruby.core.CoreLibrary;
import org.truffleruby.language.loader.ResourceLoader;
import org.truffleruby.parser.ParseEnvironment;
import org.truffleruby.parser.ParserContext;
import org.truffleruby.parser.RubySource;
import org.truffleruby.parser.YARPTranslatorDriver;
import org.truffleruby.shared.options.OptionsCatalog;
Expand All @@ -39,7 +37,7 @@ public final class ParserCache {
final Map<String, Pair<ParseResult, Source>> cache = new HashMap<>();

for (String coreFile : CoreLibrary.CORE_FILES) {
//intern() to improve footprint
// intern() to improve footprint
final String path = (defaultCoreLibraryPath + coreFile).intern();
final RubySource source = loadSource(path);
cache.put(path, parse(source));
Expand All @@ -62,14 +60,13 @@ private static RubySource loadSource(String feature) {
}

private static Pair<ParseResult, Source> parse(RubySource source) {
var language = RubyLanguage.getCurrentLanguage();
var yarpSource = YARPTranslatorDriver.createYARPSource(source.getBytes());
var parseEnvironment = new ParseEnvironment(language, source, yarpSource, ParserContext.TOP_LEVEL, null);
var sourcePath = RubyLanguage.getCorePath(source.getSource()).intern();

var parseResult = YARPTranslatorDriver.parseToYARPAST(language, source, Collections.emptyList(),
parseEnvironment);
var parseResult = YARPTranslatorDriver.parseToYARPAST(source, sourcePath, yarpSource, Collections.emptyList(),
false);

YARPTranslatorDriver.handleWarningsErrorsNoContext(language, parseResult, source, yarpSource);
YARPTranslatorDriver.handleWarningsErrorsNoContext(parseResult, sourcePath, yarpSource);

return Pair.create(parseResult, source.getSource());
}
Expand Down
9 changes: 4 additions & 5 deletions src/main/java/org/truffleruby/debug/TruffleDebugNodes.java
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@
import com.oracle.truffle.api.nodes.NodeUtil;
import com.oracle.truffle.api.object.Shape;
import com.oracle.truffle.api.utilities.TriState;
import org.truffleruby.parser.ParseEnvironment;
import org.truffleruby.parser.ParserContext;
import org.truffleruby.parser.RubySource;
import org.truffleruby.parser.TranslatorEnvironment;
Expand Down Expand Up @@ -261,12 +260,12 @@ Object ast(Object code,
var source = Source.newBuilder("ruby", new ByteBasedCharSequence(codeString), name).build();
var rubySource = new RubySource(source, name);

var language = getLanguage();
var yarpSource = YARPTranslatorDriver.createYARPSource(rubySource.getBytes());
var parseEnvironment = new ParseEnvironment(getLanguage(), rubySource, yarpSource, ParserContext.TOP_LEVEL,
this);
String sourcePath = rubySource.getSourcePath(language).intern();

var parseResult = YARPTranslatorDriver.parseToYARPAST(getLanguage(), rubySource, Collections.emptyList(),
parseEnvironment);
var parseResult = YARPTranslatorDriver.parseToYARPAST(rubySource, sourcePath, yarpSource,
Collections.emptyList(), language.options.FROZEN_STRING_LITERALS);
var ast = parseResult.value;

return createString(fromJavaStringNode, ast.toString(), Encodings.UTF_8);
Expand Down
37 changes: 13 additions & 24 deletions src/main/java/org/truffleruby/parser/YARPTranslatorDriver.java
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ public RootCallTarget parse(RubySource rubySource, ParserContext parserContext,
// Parse to the YARP AST
final RubyDeferredWarnings rubyWarnings = new RubyDeferredWarnings();

final String sourcePath = rubySource.getSourcePath(language).intern();

// Only use the cache while loading top-level core library files, as eval() later could use
// the same Source name but should not use the cache. For instance,
// TOPLEVEL_BINDING.eval("self") would use the cache which is wrong.
Expand All @@ -168,12 +170,12 @@ public RootCallTarget parse(RubySource rubySource, ParserContext parserContext,
parseResult = context.getMetricsProfiler().callWithMetrics(
"parsing",
source.getName(),
() -> parseToYARPAST(language, rubySource, localsInScopes,
parseEnvironment));
() -> parseToYARPAST(rubySource, sourcePath, yarpSource, localsInScopes,
language.options.FROZEN_STRING_LITERALS));
printParseTranslateExecuteMetric("after-parsing", context, source);
}

handleWarningsErrorsPrimitives(context, language, parseResult, rubySource, parseEnvironment, rubyWarnings);
handleWarningsErrorsPrimitives(context, parseResult, rubySource, sourcePath, parseEnvironment, rubyWarnings);

var node = parseResult.value;

Expand Down Expand Up @@ -355,18 +357,14 @@ private String getMethodName(ParserContext parserContext, MaterializedFrame pare
}
}

public static ParseResult parseToYARPAST(RubyLanguage language, RubySource rubySource,
List<List<String>> localsInScopes, ParseEnvironment parseEnvironment) {
public static ParseResult parseToYARPAST(RubySource rubySource, String sourcePath, Nodes.Source yarpSource,
List<List<String>> localsInScopes, boolean frozenStringLiteral) {
TruffleSafepoint.poll(DummyNode.INSTANCE);

// intern() to improve footprint
String sourcePath = rubySource.getSourcePath(language).intern();

byte[] sourceBytes = rubySource.getBytes();
final byte[] filepath = sourcePath.getBytes(Encodings.FILESYSTEM_CHARSET);
int line = rubySource.getLineOffset() + 1;
byte[] encoding = StringOperations.encodeAsciiBytes(rubySource.getEncoding().toString()); // encoding name is supposed to contain only ASCII characters
boolean frozenStringLiteral = language.options.FROZEN_STRING_LITERALS;
var version = ParsingOptions.SyntaxVersion.V3_3_0;

byte[][][] scopes;
Expand Down Expand Up @@ -400,17 +398,13 @@ public static ParseResult parseToYARPAST(RubyLanguage language, RubySource rubyS
scopes);
byte[] serializedBytes = Parser.parseAndSerialize(sourceBytes, parsingOptions);

Nodes.Source yarpSource = parseEnvironment.yarpSource;
return YARPLoader.load(serializedBytes, yarpSource, rubySource);
}

public static void handleWarningsErrorsPrimitives(RubyContext context, RubyLanguage language,
ParseResult parseResult, RubySource rubySource, ParseEnvironment parseEnvironment,
public static void handleWarningsErrorsPrimitives(RubyContext context, ParseResult parseResult,
RubySource rubySource, String sourcePath, ParseEnvironment parseEnvironment,
RubyDeferredWarnings rubyWarnings) {

// intern() to improve footprint
String sourcePath = rubySource.getSourcePath(language).intern();

final ParseResult.Error[] errors = parseResult.errors;

// collect warnings generated by the parser
Expand Down Expand Up @@ -464,25 +458,20 @@ public static void handleWarningsErrorsPrimitives(RubyContext context, RubyLangu
parseEnvironment.allowTruffleRubyPrimitives = allowTruffleRubyPrimitives;
}

public static void handleWarningsErrorsNoContext(RubyLanguage language, ParseResult parseResult,
RubySource rubySource, Nodes.Source yarpSource) {
public static void handleWarningsErrorsNoContext(ParseResult parseResult, String sourcePath,
Nodes.Source yarpSource) {
if (parseResult.errors.length > 0) {
var error = parseResult.errors[0];
throw CompilerDirectives.shouldNotReachHere("Parse error in " +
fileLineYARPSource(error.location, language, rubySource, yarpSource) + ": " + error.message);
sourcePath + ":" + yarpSource.line(error.location.startOffset) + ": " + error.message);
}

for (var warning : parseResult.warnings) {
throw CompilerDirectives.shouldNotReachHere("Warning in " +
fileLineYARPSource(warning.location, language, rubySource, yarpSource) + ": " + warning.message);
sourcePath + ":" + yarpSource.line(warning.location.startOffset) + ": " + warning.message);
}
}

private static String fileLineYARPSource(Nodes.Location location, RubyLanguage language, RubySource rubySource,
Nodes.Source yarpSource) {
return rubySource.getSourcePath(language) + ":" + yarpSource.line(location.startOffset);
}

public static Nodes.Source createYARPSource(byte[] sourceBytes) {
return new Nodes.Source(sourceBytes);
}
Expand Down

0 comments on commit 610cea3

Please sign in to comment.