Skip to content

Commit

Permalink
[GR-36526] Handle relative path issue for tools.
Browse files Browse the repository at this point in the history
PullRequest: graal/16615
  • Loading branch information
boris-spas committed Jan 25, 2024
2 parents 7ea1157 + 06fb0c6 commit 7c196cf
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
*
* It is assumed that a field of type c may hold a reference to any subtype of c. It is also assumed
* that any subtype of c is instantiated.
*
* This annotation is only necessary during the image build. It prevents the static analysis from
* wrongly constant-folding a value that is initialized late during the image build and therefore
* not available during analysis.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,13 @@

import com.oracle.svm.core.BuildPhaseProvider.AfterAnalysis;

/** For fields with this annotation no static analysis is done. */
/**
* For fields with this annotation no static analysis is done.
*
* This annotation is only necessary during the image build. It prevents the static analysis from
* wrongly constant-folding a value that is initialized late during the image build and therefore
* not available during analysis.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Platforms(Platform.HOSTED_ONLY.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,15 @@ public Output apply(String s) {
private CoverageTracker tracker;
private Boolean enabled;

/*
* Guest languages could change the working directory of the current process, The JVM assumes
* that the working directory does not change. When this assumption is broken relative file
* paths no longer work correctly. For this reason we save the absolute path to the output file
* at the very start so that we avoid issues of broken relative paths See GR-36526 for more
* context.
*/
private String absoluteOutputPath;

public static CoverageTracker getTracker(Engine engine) {
Instrument instrument = engine.getInstruments().get(ID);
if (instrument == null) {
Expand All @@ -123,11 +132,10 @@ public static void setFactory(Function<Env, CoverageTracker> factory) {
CoverageInstrument.factory = factory;
}

protected static PrintStream chooseOutputStream(TruffleInstrument.Env env, OptionKey<String> option) {
protected static PrintStream chooseOutputStream(Env env, String absoluteOutputPath) {
try {
if (option.hasBeenSet(env.getOptions())) {
final String outputPath = option.getValue(env.getOptions());
final File file = new File(outputPath);
if (absoluteOutputPath != null) {
final File file = new File(absoluteOutputPath);
new PrintStream(env.out()).println("Printing output to " + file.getAbsolutePath());
return new PrintStream(new FileOutputStream(file));
} else {
Expand Down Expand Up @@ -171,6 +179,9 @@ protected void onCreate(Env env) {
enabled = ENABLED.getValue(options);
if (enabled) {
tracker.start(new CoverageTracker.Config(getSourceSectionFilter(options), Count.getValue(options)));
if (CoverageInstrument.OUTPUT_FILE.hasBeenSet(env.getOptions())) {
absoluteOutputPath = new File(CoverageInstrument.OUTPUT_FILE.getValue(env.getOptions())).getAbsolutePath();
}
}
}

Expand All @@ -180,7 +191,7 @@ protected void onFinalize(Env env) {
SourceCoverage[] coverage = tracker.getCoverage();
final OptionValues options = env.getOptions();
final boolean strictLines = StrictLines.getValue(options);
PrintStream out = chooseOutputStream(env, OUTPUT_FILE);
PrintStream out = chooseOutputStream(env, absoluteOutputPath);
switch (OUTPUT.getValue(options)) {
case HISTOGRAM:
new CoverageCLI(out, coverage, strictLines).printHistogramOutput();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,15 @@
import org.graalvm.options.OptionStability;
import org.graalvm.options.OptionType;
import org.graalvm.options.OptionValues;
import org.graalvm.shadowed.org.json.JSONArray;
import org.graalvm.shadowed.org.json.JSONObject;

import com.oracle.truffle.api.Option;
import com.oracle.truffle.api.TruffleContext;
import com.oracle.truffle.api.instrumentation.TruffleInstrument;
import com.oracle.truffle.tools.profiler.CPUSampler;
import com.oracle.truffle.tools.profiler.CPUSamplerData;
import com.oracle.truffle.tools.profiler.ProfilerNode;
import org.graalvm.shadowed.org.json.JSONArray;
import org.graalvm.shadowed.org.json.JSONObject;

@Option.Group(CPUSamplerInstrument.ID)
class CPUSamplerCLI extends ProfilerCLI {
Expand Down Expand Up @@ -221,8 +221,8 @@ public int[] apply(String s) {
@Option(name = "SampleContextInitialization", help = "Enables sampling of code executed during context initialization", category = OptionCategory.EXPERT, stability = OptionStability.STABLE) //
static final OptionKey<Boolean> SAMPLE_CONTEXT_INITIALIZATION = new OptionKey<>(false);

static void handleOutput(TruffleInstrument.Env env, CPUSampler sampler) {
PrintStream out = chooseOutputStream(env);
static void handleOutput(TruffleInstrument.Env env, CPUSampler sampler, String absoluteOutputPath) {
PrintStream out = chooseOutputStream(env, absoluteOutputPath);
Map<TruffleContext, CPUSamplerData> data = sampler.getData();
OptionValues options = env.getOptions();
switch (chooseOutput(options)) {
Expand All @@ -242,12 +242,10 @@ static void handleOutput(TruffleInstrument.Env env, CPUSampler sampler) {
}
}

private static PrintStream chooseOutputStream(TruffleInstrument.Env env) {
OptionValues options = env.getOptions();
final String outputPath = getOutputPath(env, options);
if (outputPath != null) {
private static PrintStream chooseOutputStream(TruffleInstrument.Env env, String absoluteOutputPath) {
if (absoluteOutputPath != null) {
try {
final File file = new File(outputPath);
final File file = new File(absoluteOutputPath);
new PrintStream(env.out()).println("Printing output to " + file.getAbsolutePath());
return new PrintStream(new FileOutputStream(file));
} catch (FileNotFoundException e) {
Expand All @@ -257,9 +255,9 @@ private static PrintStream chooseOutputStream(TruffleInstrument.Env env) {
return new PrintStream(env.out());
}

private static String getOutputPath(TruffleInstrument.Env env, OptionValues options) {
static String getOutputPath(OptionValues options) {
if (OUTPUT_FILE.hasBeenSet(options)) {
return OUTPUT_FILE.getValue(env.getOptions());
return OUTPUT_FILE.getValue(options);
}
if (ENABLED.getValue(options).output == Output.FLAMEGRAPH) {
return DEFAULT_FLAMEGRAPH_FILE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import static com.oracle.truffle.tools.profiler.impl.CPUSamplerCLI.GATHER_HIT_TIMES;
import static com.oracle.truffle.tools.profiler.impl.CPUSamplerCLI.SAMPLE_CONTEXT_INITIALIZATION;

import java.io.File;
import java.lang.reflect.Method;

import org.graalvm.options.OptionDescriptors;
Expand Down Expand Up @@ -61,9 +62,18 @@ public CPUSamplerInstrument() {
* @since 0.30
*/
public static final String ID = "cpusampler";
private static final ProfilerToolFactory<CPUSampler> factory = getDefaultFactory();
static final String VERSION = "0.5.0";
private CPUSampler sampler;
private static final ProfilerToolFactory<CPUSampler> factory = getDefaultFactory();

/*
* Guest languages could change the working directory of the current process, The JVM assumes
* that the working directory does not change. When this assumption is broken relative file
* paths no longer work correctly. For this reason we save the absolute path to the output file
* at the very start so that we avoid issues of broken relative paths See GR-36526 for more
* context.
*/
private String absoluteOutputPath;

@SuppressWarnings("unchecked")
private static ProfilerToolFactory<CPUSampler> getDefaultFactory() {
Expand Down Expand Up @@ -109,6 +119,8 @@ protected void onCreate(Env env) {
sampler.setGatherSelfHitTimes(options.get(GATHER_HIT_TIMES));
sampler.setSampleContextInitialization(options.get(SAMPLE_CONTEXT_INITIALIZATION));
sampler.setCollecting(true);
String outputPath = CPUSamplerCLI.getOutputPath(options);
absoluteOutputPath = (outputPath != null) ? new File(outputPath).getAbsolutePath() : null;
}
env.registerService(sampler);
}
Expand Down Expand Up @@ -142,7 +154,7 @@ protected void onFinalize(Env env) {
OptionValues options = env.getOptions();
CPUSamplerCLI.EnableOptionData enableOptionData = options.get(CPUSamplerCLI.ENABLED);
if (enableOptionData.enabled) {
CPUSamplerCLI.handleOutput(env, sampler);
CPUSamplerCLI.handleOutput(env, sampler, absoluteOutputPath);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
*/
package com.oracle.truffle.tools.profiler.impl;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collection;
Expand All @@ -36,12 +39,12 @@
import org.graalvm.options.OptionKey;
import org.graalvm.options.OptionStability;
import org.graalvm.options.OptionType;
import org.graalvm.shadowed.org.json.JSONArray;
import org.graalvm.shadowed.org.json.JSONObject;

import com.oracle.truffle.api.Option;
import com.oracle.truffle.api.instrumentation.TruffleInstrument;
import com.oracle.truffle.tools.profiler.CPUTracer;
import org.graalvm.shadowed.org.json.JSONArray;
import org.graalvm.shadowed.org.json.JSONObject;

@Option.Group(CPUTracerInstrument.ID)
class CPUTracerCLI extends ProfilerCLI {
Expand Down Expand Up @@ -101,8 +104,8 @@ public Output apply(String s) {
@Option(name = "OutputFile", help = "Save output to the given file. Output is printed to standard output stream by default.", usageSyntax = "<path>", category = OptionCategory.USER, stability = OptionStability.STABLE) //
static final OptionKey<String> OUTPUT_FILE = new OptionKey<>("");

public static void handleOutput(TruffleInstrument.Env env, CPUTracer tracer) {
PrintStream out = chooseOutputStream(env, OUTPUT_FILE);
public static void handleOutput(TruffleInstrument.Env env, CPUTracer tracer, String absoluteOutputPath) {
PrintStream out = chooseOutputStream(env, absoluteOutputPath);
switch (env.getOptions().get(OUTPUT)) {
case HISTOGRAM:
printTracerHistogram(out, tracer);
Expand All @@ -113,6 +116,19 @@ public static void handleOutput(TruffleInstrument.Env env, CPUTracer tracer) {
}
}

protected static PrintStream chooseOutputStream(TruffleInstrument.Env env, String absoluteOutputPath) {
try {
if (absoluteOutputPath != null) {
final File file = new File(absoluteOutputPath);
return new PrintStream(new FileOutputStream(file));
} else {
return new PrintStream(env.out());
}
} catch (FileNotFoundException e) {
throw handleFileNotFound();
}
}

private static void printTracerJson(PrintStream out, CPUTracer tracer) {
JSONObject output = new JSONObject();
output.put("tool", CPUTracerInstrument.ID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
*/
package com.oracle.truffle.tools.profiler.impl;

import java.io.File;
import java.io.PrintStream;
import java.lang.reflect.Method;

Expand Down Expand Up @@ -58,11 +59,19 @@ public CPUTracerInstrument() {
* @since 0.30
*/
public static final String ID = "cputracer";
private static final ProfilerToolFactory<CPUTracer> factory = getDefaultFactory();

static final String VERSION = "0.3.0";
private boolean enabled;
private CPUTracer tracer;
private static final ProfilerToolFactory<CPUTracer> factory = getDefaultFactory();
/*
* Guest languages could change the working directory of the current process, The JVM assumes
* that the working directory does not change. When this assumption is broken relative file
* paths no longer work correctly. For this reason we save the absolute path to the output file
* at the very start so that we avoid issues of broken relative paths See GR-36526 for more
* context.
*/
String absoluteOutputPath;

@SuppressWarnings("unchecked")
private static ProfilerToolFactory<CPUTracer> getDefaultFactory() {
Expand Down Expand Up @@ -111,6 +120,10 @@ protected void onCreate(Env env) {
return;
}
tracer.setCollecting(true);
if (CPUTracerCLI.OUTPUT_FILE.hasBeenSet(env.getOptions())) {
final String outputPath = CPUTracerCLI.OUTPUT_FILE.getValue(env.getOptions());
absoluteOutputPath = new File(outputPath).getAbsolutePath();
}
}
env.registerService(tracer);
}
Expand Down Expand Up @@ -145,7 +158,7 @@ protected OptionDescriptors getOptionDescriptors() {
@Override
protected void onFinalize(Env env) {
if (enabled) {
CPUTracerCLI.handleOutput(env, tracer);
CPUTracerCLI.handleOutput(env, tracer, absoluteOutputPath);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@
package com.oracle.truffle.tools.profiler.impl;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
Expand All @@ -36,15 +33,13 @@
import java.util.function.Predicate;
import java.util.regex.Pattern;

import org.graalvm.options.OptionKey;
import org.graalvm.shadowed.org.json.JSONObject;

import com.oracle.truffle.api.exception.AbstractTruffleException;
import com.oracle.truffle.api.instrumentation.SourceSectionFilter;
import com.oracle.truffle.api.instrumentation.StandardTags;
import com.oracle.truffle.api.instrumentation.TruffleInstrument;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;
import org.graalvm.shadowed.org.json.JSONObject;

abstract class ProfilerCLI {

Expand Down Expand Up @@ -237,20 +232,6 @@ public int hashCode() {
}
}

protected static PrintStream chooseOutputStream(TruffleInstrument.Env env, OptionKey<String> option) {
try {
if (option.hasBeenSet(env.getOptions())) {
final String outputPath = option.getValue(env.getOptions());
final File file = new File(outputPath);
return new PrintStream(new FileOutputStream(file));
} else {
return new PrintStream(env.out());
}
} catch (FileNotFoundException e) {
throw handleFileNotFound();
}
}

protected static AbstractTruffleException handleFileNotFound() {
return new AbstractTruffleException() {
static final long serialVersionUID = -1;
Expand Down

0 comments on commit 7c196cf

Please sign in to comment.