From ea5fc1c692abb5b534fe96a802824231ece089de Mon Sep 17 00:00:00 2001 From: David Kozak Date: Tue, 14 Sep 2021 14:41:30 +0200 Subject: [PATCH 01/65] create AbstractAnalysisEngine taking care of the generic static analysis engine methods --- .../pointsto/AbstractAnalysisEngine.java | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java new file mode 100644 index 000000000000..90009da3ee92 --- /dev/null +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.pointsto; + +import com.oracle.graal.pointsto.AnalysisPolicy; +import com.oracle.graal.pointsto.BigBang; +import com.oracle.graal.pointsto.HeapScanningPolicy; +import com.oracle.graal.pointsto.api.HostVM; +import com.oracle.graal.pointsto.api.PointstoOptions; +import com.oracle.graal.pointsto.constraints.UnsupportedFeatures; +import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; +import com.oracle.graal.pointsto.meta.AnalysisType; +import com.oracle.graal.pointsto.meta.AnalysisUniverse; +import com.oracle.graal.pointsto.meta.HostedProviders; +import com.oracle.graal.pointsto.reports.StatisticsPrinter; +import com.oracle.graal.pointsto.util.Timer; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; + +import java.io.PrintWriter; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ForkJoinPool; + +public abstract class AbstractAnalysisEngine implements BigBang { + + private final Boolean extendedAsserts; + private final Timer processFeaturesTimer; + private final Timer analysisTimer; + private final AnalysisMetaAccess metaAccess; + private final HostedProviders providers; + private final HostVM hostVM; + private final Runnable heartbeatCallback; + private final UnsupportedFeatures unsupportedFeatures; + private final DebugContext debug; + private final OptionValues options; + private final AnalysisUniverse universe; + private final List debugHandlerFactories; + private final HeapScanningPolicy heapScanningPolicy; + + public AbstractAnalysisEngine(OptionValues options, AnalysisUniverse universe, HostedProviders providers, HostVM hostVM, ForkJoinPool executorService, Runnable heartbeatCallback, + UnsupportedFeatures unsupportedFeatures) { + this.options = options; + this.universe = universe; + this.debugHandlerFactories = Collections.singletonList(new GraalDebugHandlersFactory(providers.getSnippetReflection())); + this.debug = new org.graalvm.compiler.debug.DebugContext.Builder(options, debugHandlerFactories).build(); + this.metaAccess = (AnalysisMetaAccess) providers.getMetaAccess(); + this.providers = providers; + this.hostVM = hostVM; + this.heartbeatCallback = heartbeatCallback; + this.unsupportedFeatures = unsupportedFeatures; + + String imageName = hostVM.getImageName(); + this.processFeaturesTimer = new Timer(imageName, "(features)", false); + this.analysisTimer = new Timer(imageName, "analysis", true); + + this.extendedAsserts = PointstoOptions.ExtendedAsserts.getValue(options); + + this.heapScanningPolicy = PointstoOptions.ExhaustiveHeapScan.getValue(options) + ? HeapScanningPolicy.scanAll() + : HeapScanningPolicy.skipTypes(skippedHeapTypes()); + } + + @Override + public Timer getAnalysisTimer() { + return analysisTimer; + } + + @Override + public Timer getProcessFeaturesTimer() { + return processFeaturesTimer; + } + + @Override + public void printTimers() { + processFeaturesTimer.print(); + } + + @Override + public void printTimerStatistics(PrintWriter out) { + StatisticsPrinter.print(out, "features_time_ms", processFeaturesTimer.getTotalTime()); + StatisticsPrinter.print(out, "total_analysis_time_ms", analysisTimer.getTotalTime()); + + StatisticsPrinter.printLast(out, "total_memory_bytes", analysisTimer.getTotalMemory()); + } + + @Override + public AnalysisType[] skippedHeapTypes() { + return new AnalysisType[]{metaAccess.lookupJavaType(String.class)}; + } + + @Override + public boolean extendedAsserts() { + return extendedAsserts; + } + + @Override + public OptionValues getOptions() { + return options; + } + + @Override + public Runnable getHeartbeatCallback() { + return heartbeatCallback; + } + + @Override + public DebugContext getDebug() { + return debug; + } + + @Override + public List getDebugHandlerFactories() { + return debugHandlerFactories; + } + + @Override + public AnalysisPolicy analysisPolicy() { + return universe.analysisPolicy(); + } + + @Override + public AnalysisUniverse getUniverse() { + return universe; + } + + @Override + public HostedProviders getProviders() { + return providers; + } + + @Override + public AnalysisMetaAccess getMetaAccess() { + return metaAccess; + } + + @Override + public UnsupportedFeatures getUnsupportedFeatures() { + return unsupportedFeatures; + } + + @Override + public final SnippetReflectionProvider getSnippetReflectionProvider() { + return providers.getSnippetReflection(); + } + + @Override + public final ConstantReflectionProvider getConstantReflectionProvider() { + return providers.getConstantReflection(); + } + + @Override + public HeapScanningPolicy scanningPolicy() { + return heapScanningPolicy; + } + + @Override + public HostVM getHostVM() { + return hostVM; + } + +} From a6395fb5566584155e15994f732beebda49798c4 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Tue, 14 Sep 2021 14:42:34 +0200 Subject: [PATCH 02/65] introduce a new project for reachability analysis --- .../reachability/ReachabilityAnalysis.java | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java new file mode 100644 index 000000000000..314f4215e1e3 --- /dev/null +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.reachability; + +import com.oracle.graal.pointsto.AbstractAnalysisEngine; +import com.oracle.graal.pointsto.api.HostVM; +import com.oracle.graal.pointsto.constraints.UnsupportedFeatures; +import com.oracle.graal.pointsto.meta.AnalysisField; +import com.oracle.graal.pointsto.meta.AnalysisMethod; +import com.oracle.graal.pointsto.meta.AnalysisType; +import com.oracle.graal.pointsto.meta.AnalysisUniverse; +import com.oracle.graal.pointsto.meta.HostedProviders; +import com.oracle.graal.pointsto.typestate.TypeState; +import org.graalvm.compiler.options.OptionValues; + +import java.lang.reflect.Executable; +import java.util.concurrent.ForkJoinPool; + +public class ReachabilityAnalysis extends AbstractAnalysisEngine { + + public ReachabilityAnalysis(OptionValues options, AnalysisUniverse universe, HostedProviders providers, HostVM hostVM, ForkJoinPool executorService, Runnable heartbeatCallback, + UnsupportedFeatures unsupportedFeatures) { + super(options, universe, providers, hostVM, executorService, heartbeatCallback, unsupportedFeatures); + } + + @Override + public void checkUserLimitations() { + + } + + @Override + public AnalysisType addRootClass(Class clazz, boolean addFields, boolean addArrayClass) { + return null; + } + + @Override + public AnalysisType addRootField(Class clazz, String fieldName) { + return null; + } + + @Override + public AnalysisMethod addRootMethod(AnalysisMethod aMethod) { + return null; + } + + @Override + public AnalysisMethod addRootMethod(Executable method) { + return null; + } + + @Override + public AnalysisMethod addRootMethod(Class clazz, String methodName, Class... parameterTypes) { + return null; + } + + @Override + public boolean finish() throws InterruptedException { + return false; + } + + @Override + public void cleanupAfterAnalysis() { + + } + + @Override + public void forceUnsafeUpdate(AnalysisField field) { + + } + + @Override + public void registerAsJNIAccessed(AnalysisField field, boolean writable) { + + } + + @Override + public TypeState getAllSynchronizedTypeState() { + return null; + } +} From 7f506f650e55b05b3fe17782b8fa5c2e6199bc90 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Tue, 14 Sep 2021 14:57:00 +0200 Subject: [PATCH 03/65] introduce AbstractReachabilityAnalysis --- .../pointsto/AbstractAnalysisEngine.java | 14 +++-- .../AbstractReachabilityAnalysis.java | 62 +++++++++++++++++++ .../graal/pointsto/PointsToAnalysis.java | 3 +- .../graal/pointsto/ReachabilityAnalysis.java | 2 + .../reachability/ReachabilityAnalysis.java | 6 +- 5 files changed, 79 insertions(+), 8 deletions(-) create mode 100644 substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractReachabilityAnalysis.java diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java index 90009da3ee92..11ac8f7e47ac 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java @@ -24,13 +24,12 @@ */ package com.oracle.graal.pointsto; -import com.oracle.graal.pointsto.AnalysisPolicy; -import com.oracle.graal.pointsto.BigBang; -import com.oracle.graal.pointsto.HeapScanningPolicy; import com.oracle.graal.pointsto.api.HostVM; import com.oracle.graal.pointsto.api.PointstoOptions; import com.oracle.graal.pointsto.constraints.UnsupportedFeatures; +import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; +import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.graal.pointsto.meta.HostedProviders; @@ -53,7 +52,7 @@ public abstract class AbstractAnalysisEngine implements BigBang { private final Boolean extendedAsserts; private final Timer processFeaturesTimer; private final Timer analysisTimer; - private final AnalysisMetaAccess metaAccess; + protected final AnalysisMetaAccess metaAccess; private final HostedProviders providers; private final HostVM hostVM; private final Runnable heartbeatCallback; @@ -87,6 +86,13 @@ public AbstractAnalysisEngine(OptionValues options, AnalysisUniverse universe, H : HeapScanningPolicy.skipTypes(skippedHeapTypes()); } + @Override + public void cleanupAfterAnalysis() { + universe.getTypes().forEach(AnalysisType::cleanupAfterAnalysis); + universe.getFields().forEach(AnalysisField::cleanupAfterAnalysis); + universe.getMethods().forEach(AnalysisMethod::cleanupAfterAnalysis); + } + @Override public Timer getAnalysisTimer() { return analysisTimer; diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractReachabilityAnalysis.java new file mode 100644 index 000000000000..86ad12c95cb6 --- /dev/null +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractReachabilityAnalysis.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.pointsto; + +import com.oracle.graal.pointsto.api.HostVM; +import com.oracle.graal.pointsto.constraints.UnsupportedFeatures; +import com.oracle.graal.pointsto.meta.AnalysisMethod; +import com.oracle.graal.pointsto.meta.AnalysisType; +import com.oracle.graal.pointsto.meta.AnalysisUniverse; +import com.oracle.graal.pointsto.meta.HostedProviders; +import org.graalvm.compiler.options.OptionValues; + +import java.lang.reflect.Method; +import java.util.concurrent.ForkJoinPool; + +import static jdk.vm.ci.common.JVMCIError.shouldNotReachHere; + +public abstract class AbstractReachabilityAnalysis extends AbstractAnalysisEngine { + public AbstractReachabilityAnalysis(OptionValues options, AnalysisUniverse universe, HostedProviders providers, HostVM hostVM, ForkJoinPool executorService, Runnable heartbeatCallback, + UnsupportedFeatures unsupportedFeatures) { + super(options, universe, providers, hostVM, executorService, heartbeatCallback, unsupportedFeatures); + } + + @Override + public AnalysisType addRootClass(Class clazz, boolean addFields, boolean addArrayClass) { + AnalysisType type = metaAccess.lookupJavaType(clazz); + type.registerAsReachable(); + return addRootClass(type, addFields, addArrayClass); + } + + @Override + public AnalysisMethod addRootMethod(Class clazz, String methodName, Class... parameterTypes) { + try { + Method method = clazz.getDeclaredMethod(methodName, parameterTypes); + return addRootMethod(method); + } catch (NoSuchMethodException ex) { + throw shouldNotReachHere(ex); + } + } +} diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java index 6bab1c026d9e..9139547fc1e9 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java @@ -485,7 +485,8 @@ public AnalysisType addRootClass(Class clazz, boolean addFields, boolean addA } @SuppressWarnings({"try"}) - private AnalysisType addRootClass(AnalysisType type, boolean addFields, boolean addArrayClass) { + @Override + public AnalysisType addRootClass(AnalysisType type, boolean addFields, boolean addArrayClass) { try (Indent indent = debug.logAndIndent("add root class %s", type.getName())) { for (AnalysisField field : type.getInstanceFields(false)) { if (addFields) { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ReachabilityAnalysis.java index 88eebb9c1c54..9c84c4c1e817 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ReachabilityAnalysis.java @@ -50,6 +50,8 @@ public interface ReachabilityAnalysis { */ AnalysisType addRootClass(Class clazz, boolean addFields, boolean addArrayClass); + AnalysisType addRootClass(AnalysisType type, boolean addFields, boolean addArrayClass); + /** * Marks given field as accessed. */ diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index 314f4215e1e3..6711558ad8ec 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -24,7 +24,7 @@ */ package com.oracle.graal.reachability; -import com.oracle.graal.pointsto.AbstractAnalysisEngine; +import com.oracle.graal.pointsto.AbstractReachabilityAnalysis; import com.oracle.graal.pointsto.api.HostVM; import com.oracle.graal.pointsto.constraints.UnsupportedFeatures; import com.oracle.graal.pointsto.meta.AnalysisField; @@ -38,7 +38,7 @@ import java.lang.reflect.Executable; import java.util.concurrent.ForkJoinPool; -public class ReachabilityAnalysis extends AbstractAnalysisEngine { +public class ReachabilityAnalysis extends AbstractReachabilityAnalysis { public ReachabilityAnalysis(OptionValues options, AnalysisUniverse universe, HostedProviders providers, HostVM hostVM, ForkJoinPool executorService, Runnable heartbeatCallback, UnsupportedFeatures unsupportedFeatures) { @@ -51,7 +51,7 @@ public void checkUserLimitations() { } @Override - public AnalysisType addRootClass(Class clazz, boolean addFields, boolean addArrayClass) { + public AnalysisType addRootClass(AnalysisType type, boolean addFields, boolean addArrayClass) { return null; } From d28a05ab33823d60830f8e5b48bbcf98b450a67b Mon Sep 17 00:00:00 2001 From: David Kozak Date: Tue, 14 Sep 2021 15:10:26 +0200 Subject: [PATCH 04/65] implement the first part of reachability analysis methods --- .../pointsto/AbstractAnalysisEngine.java | 2 +- .../AbstractReachabilityAnalysis.java | 8 +++ .../reachability/ReachabilityAnalysis.java | 55 ++++++++++++------- 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java index 11ac8f7e47ac..ebe07b31d617 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java @@ -57,7 +57,7 @@ public abstract class AbstractAnalysisEngine implements BigBang { private final HostVM hostVM; private final Runnable heartbeatCallback; private final UnsupportedFeatures unsupportedFeatures; - private final DebugContext debug; + protected final DebugContext debug; private final OptionValues options; private final AnalysisUniverse universe; private final List debugHandlerFactories; diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractReachabilityAnalysis.java index 86ad12c95cb6..f74f23a0921e 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractReachabilityAnalysis.java @@ -32,6 +32,7 @@ import com.oracle.graal.pointsto.meta.HostedProviders; import org.graalvm.compiler.options.OptionValues; +import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.util.concurrent.ForkJoinPool; @@ -59,4 +60,11 @@ public AnalysisMethod addRootMethod(Class clazz, String methodName, Class. throw shouldNotReachHere(ex); } } + + @Override + public AnalysisMethod addRootMethod(Executable method) { + AnalysisMethod aMethod = metaAccess.lookupJavaMethod(method); + addRootMethod(aMethod); + return aMethod; + } } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index 6711558ad8ec..14e2ea13baac 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -33,46 +33,63 @@ import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.graal.pointsto.meta.HostedProviders; import com.oracle.graal.pointsto.typestate.TypeState; +import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.options.OptionValues; import java.lang.reflect.Executable; import java.util.concurrent.ForkJoinPool; -public class ReachabilityAnalysis extends AbstractReachabilityAnalysis { +import static jdk.vm.ci.common.JVMCIError.shouldNotReachHere; + +public abstract class ReachabilityAnalysis extends AbstractReachabilityAnalysis { public ReachabilityAnalysis(OptionValues options, AnalysisUniverse universe, HostedProviders providers, HostVM hostVM, ForkJoinPool executorService, Runnable heartbeatCallback, UnsupportedFeatures unsupportedFeatures) { super(options, universe, providers, hostVM, executorService, heartbeatCallback, unsupportedFeatures); } - @Override - public void checkUserLimitations() { - - } - @Override public AnalysisType addRootClass(AnalysisType type, boolean addFields, boolean addArrayClass) { - return null; + // todo async + try (Indent indent = debug.logAndIndent("add root class %s", type.getName())) { + for (AnalysisField field : type.getInstanceFields(false)) { + if (addFields) { + field.registerAsAccessed(); + } + } + if (type.getSuperclass() != null) { + addRootClass(type.getSuperclass(), addFields, addArrayClass); + } + if (addArrayClass) { + addRootClass(type.getArrayClass(), false, false); + } + } + return type; } @Override public AnalysisType addRootField(Class clazz, String fieldName) { - return null; + // todo async + AnalysisType type = addRootClass(clazz, false, false); + for (AnalysisField field : type.getInstanceFields(true)) { + if (field.getName().equals(fieldName)) { + try (Indent indent = debug.logAndIndent("add root field %s in class %s", fieldName, clazz.getName())) { + field.registerAsAccessed(); + } + return field.getType(); + } + } + throw shouldNotReachHere("field not found: " + fieldName); } @Override public AnalysisMethod addRootMethod(AnalysisMethod aMethod) { - return null; + throw new RuntimeException("unfinished"); } @Override public AnalysisMethod addRootMethod(Executable method) { - return null; - } - - @Override - public AnalysisMethod addRootMethod(Class clazz, String methodName, Class... parameterTypes) { - return null; + throw new RuntimeException("unfinished"); } @Override @@ -82,21 +99,21 @@ public boolean finish() throws InterruptedException { @Override public void cleanupAfterAnalysis() { - + super.cleanupAfterAnalysis(); } @Override public void forceUnsafeUpdate(AnalysisField field) { - + throw new RuntimeException("unfinished"); } @Override public void registerAsJNIAccessed(AnalysisField field, boolean writable) { - + throw new RuntimeException("unfinished"); } @Override public TypeState getAllSynchronizedTypeState() { - return null; + throw new RuntimeException("unfinished"); } } From c159c90c7290d58703a9c7fffc558d2d59f4ba71 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Wed, 15 Sep 2021 17:16:06 +0200 Subject: [PATCH 05/65] continue implementing the reachability analysis --- substratevm/mx.substratevm/suite.py | 1 + .../pointsto/AbstractAnalysisEngine.java | 15 +++- .../com/oracle/graal/pointsto/BigBang.java | 2 + .../graal/pointsto/PointsToAnalysis.java | 1 + .../graal/pointsto/meta/AnalysisMethod.java | 8 +- .../graal/pointsto/meta/AnalysisType.java | 30 +++++++ .../AbstractAnalysisResultsBuilder.java | 5 +- .../pointsto/results/DummyResultsBuilder.java | 25 ++++++ .../results/StaticAnalysisResultsBuilder.java | 6 +- .../pointsto/results/StrengthenGraphs.java | 3 + .../graal/reachability/MethodSummary.java | 38 ++++++++ .../reachability/MethodSummaryProvider.java | 31 +++++++ .../reachability/ReachabilityAnalysis.java | 87 ++++++++++++++++--- .../SimpleInMemoryMethodSummaryProvider.java | 38 ++++++++ .../svm/hosted/HostedConfiguration.java | 6 +- .../svm/hosted/NativeImageGenerator.java | 15 +++- .../oracle/svm/hosted/NativeImageOptions.java | 3 + .../NativeImageReachabilityAnalysis.java | 69 +++++++++++++++ 18 files changed, 362 insertions(+), 21 deletions(-) create mode 100644 substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/DummyResultsBuilder.java create mode 100644 substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java create mode 100644 substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummaryProvider.java create mode 100644 substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java create mode 100644 substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index c1b51a072e91..560c8ada731d 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -415,6 +415,7 @@ "com.oracle.objectfile", "com.oracle.svm.core", "com.oracle.graal.pointsto", + "com.oracle.graal.reachability" ], "requires" : [ "java.desktop", diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java index ebe07b31d617..fbc2ff2c06bc 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java @@ -39,6 +39,7 @@ import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.printer.GraalDebugHandlersFactory; @@ -54,7 +55,8 @@ public abstract class AbstractAnalysisEngine implements BigBang { private final Timer analysisTimer; protected final AnalysisMetaAccess metaAccess; private final HostedProviders providers; - private final HostVM hostVM; + protected final HostVM hostVM; + protected final ForkJoinPool executorService; private final Runnable heartbeatCallback; private final UnsupportedFeatures unsupportedFeatures; protected final DebugContext debug; @@ -62,6 +64,7 @@ public abstract class AbstractAnalysisEngine implements BigBang { private final AnalysisUniverse universe; private final List debugHandlerFactories; private final HeapScanningPolicy heapScanningPolicy; + private final Replacements replacements; public AbstractAnalysisEngine(OptionValues options, AnalysisUniverse universe, HostedProviders providers, HostVM hostVM, ForkJoinPool executorService, Runnable heartbeatCallback, UnsupportedFeatures unsupportedFeatures) { @@ -72,8 +75,10 @@ public AbstractAnalysisEngine(OptionValues options, AnalysisUniverse universe, H this.metaAccess = (AnalysisMetaAccess) providers.getMetaAccess(); this.providers = providers; this.hostVM = hostVM; + this.executorService = executorService; this.heartbeatCallback = heartbeatCallback; this.unsupportedFeatures = unsupportedFeatures; + this.replacements = providers.getReplacements(); String imageName = hostVM.getImageName(); this.processFeaturesTimer = new Timer(imageName, "(features)", false); @@ -191,4 +196,12 @@ public HostVM getHostVM() { return hostVM; } + protected void schedule(Runnable task) { + executorService.submit(task); + } + + @Override + public Replacements getReplacements() { + return replacements; + } } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java index e5ce0dc53b71..c278ad7368e1 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java @@ -104,6 +104,8 @@ public interface BigBang extends ReachabilityAnalysis, HeapScanning { void runAnalysis(DebugContext debug, Function duringAnalysisAction) throws InterruptedException; + Replacements getReplacements(); + /** You can blacklist certain callees here. */ @SuppressWarnings("unused") default boolean isCallAllowed(PointsToAnalysis bb, AnalysisMethod caller, AnalysisMethod target, NodeSourcePosition srcPosition) { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java index 9139547fc1e9..08d9776ec0b1 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java @@ -357,6 +357,7 @@ public AnalysisMetaAccess getMetaAccess() { return metaAccess; } + @Override public Replacements getReplacements() { return replacements; } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java index 9f7cce7c7e13..3cbf3df0450e 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java @@ -213,7 +213,13 @@ public void registerAsEntryPoint(Object newEntryPointData) { } public boolean registerAsInvoked() { - return AtomicUtils.atomicMark(isInvoked); + if (AtomicUtils.atomicMark(isInvoked)) { + getDeclaringClass() + .getInvokedMethods() + .add(this); + return true; + } + return false; } public boolean registerAsImplementationInvoked() { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java index b19bd086af29..7036b9deface 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java @@ -107,6 +107,9 @@ public class AnalysisType implements WrappedJavaType, OriginalClassProvider, Com private final Set subTypes; AnalysisType superClass; + private final Set instantiatedSubtypes = ConcurrentHashMap.newKeySet(); + private final Set invokedMethods = ConcurrentHashMap.newKeySet(); + private final int id; private final JavaKind storageKind; @@ -419,6 +422,7 @@ public static boolean verifyAssignableTypes(BigBang bb) { public boolean registerAsInHeap() { registerAsReachable(); if (AtomicUtils.atomicMark(isInHeap)) { + registerAsInstantiated(UsageKind.InHeap); universe.onTypeInstantiated(this, UsageKind.InHeap); return true; } @@ -431,18 +435,36 @@ public boolean registerAsInHeap() { public boolean registerAsAllocated(Node node) { registerAsReachable(); if (AtomicUtils.atomicMark(isAllocated)) { + registerAsInstantiated(UsageKind.Allocated); universe.onTypeInstantiated(this, UsageKind.Allocated); return true; } return false; } + /** Register the type as instantiated with all its super types. */ + private void registerAsInstantiated(UsageKind usageKind) { + assert isAllocated.get() || isInHeap.get(); + assert isArray() || (isInstanceClass() && !Modifier.isAbstract(getModifiers())) : this; + universe.hostVM.checkForbidden(this, usageKind); + + AnalysisType current = this; + while (current != null) { + current.instantiatedSubtypes.add(this); + current = current.getSuperclass(); + } + } + /** * Register the type as assignable with all its super types. This is a blocking call to ensure * that the type is registered with all its super types before it is propagated by the analysis * through type flows. */ public void registerAsAssignable(BigBang bb) { + // todo refactor + if (!(bb instanceof PointsToAnalysis)) { + return; + } TypeState typeState = TypeState.forType(((PointsToAnalysis) bb), this, true); /* * Register the assignable type with its super types. Skip this type, it can lead to a @@ -1132,4 +1154,12 @@ private ResolvedJavaField[] interceptInstanceFields(ResolvedJavaField[] fields) public interface InstanceFieldsInterceptor { ResolvedJavaField[] interceptInstanceFields(AnalysisUniverse universe, ResolvedJavaField[] fields, AnalysisType type); } + + public Set getInstantiatedSubtypes() { + return instantiatedSubtypes; + } + + public Set getInvokedMethods() { + return invokedMethods; + } } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/AbstractAnalysisResultsBuilder.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/AbstractAnalysisResultsBuilder.java index 6664431a1d04..4c9bc51017b9 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/AbstractAnalysisResultsBuilder.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/AbstractAnalysisResultsBuilder.java @@ -29,7 +29,6 @@ import java.util.Map; import com.oracle.graal.pointsto.BigBang; -import com.oracle.graal.pointsto.PointsToAnalysis; import com.oracle.graal.pointsto.api.PointstoOptions; import com.oracle.graal.pointsto.infrastructure.Universe; import com.oracle.graal.pointsto.meta.AnalysisField; @@ -43,7 +42,7 @@ public abstract class AbstractAnalysisResultsBuilder { - protected final PointsToAnalysis bb; + protected final BigBang bb; /** * The universe used to convert analysis metadata to hosted metadata, or {@code null} if no @@ -62,7 +61,7 @@ public abstract class AbstractAnalysisResultsBuilder { private final JavaMethodProfile[] methods1; private final Map methods; - protected AbstractAnalysisResultsBuilder(PointsToAnalysis bb, Universe converter) { + protected AbstractAnalysisResultsBuilder(BigBang bb, Universe converter) { this.bb = bb; this.converter = converter; diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/DummyResultsBuilder.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/DummyResultsBuilder.java new file mode 100644 index 000000000000..91f0d8c48daa --- /dev/null +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/DummyResultsBuilder.java @@ -0,0 +1,25 @@ +package com.oracle.graal.pointsto.results; + +import com.oracle.graal.pointsto.BigBang; +import com.oracle.graal.pointsto.PointsToAnalysis; +import com.oracle.graal.pointsto.infrastructure.Universe; +import com.oracle.graal.pointsto.meta.AnalysisField; +import com.oracle.graal.pointsto.meta.AnalysisMethod; +import jdk.vm.ci.meta.JavaTypeProfile; +import jdk.vm.ci.meta.TriState; + +public class DummyResultsBuilder extends AbstractAnalysisResultsBuilder { + public DummyResultsBuilder(BigBang bb, Universe converter) { + super(bb, converter); + } + + @Override + public StaticAnalysisResults makeOrApplyResults(AnalysisMethod method) { + return StaticAnalysisResults.NO_RESULTS; + } + + @Override + public JavaTypeProfile makeTypeProfile(AnalysisField field) { + return new JavaTypeProfile(TriState.UNKNOWN, 1, new JavaTypeProfile.ProfiledType[0]); + } +} diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StaticAnalysisResultsBuilder.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StaticAnalysisResultsBuilder.java index 36127355abe3..6777ecd49887 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StaticAnalysisResultsBuilder.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StaticAnalysisResultsBuilder.java @@ -58,9 +58,13 @@ public StaticAnalysisResultsBuilder(PointsToAnalysis bb, Universe converter) { super(bb, converter); } + PointsToAnalysis getAnalysis() { + return ((PointsToAnalysis) bb); + } + @Override public StaticAnalysisResults makeOrApplyResults(AnalysisMethod method) { - + PointsToAnalysis bb = getAnalysis(); MethodTypeFlow methodFlow = PointsToAnalysis.assertPointsToAnalysisMethod(method).getTypeFlow(); MethodFlowsGraph originalFlows = methodFlow.getOriginalMethodFlows(); diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StrengthenGraphs.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StrengthenGraphs.java index 45706782fd30..0d44fbc2839c 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StrengthenGraphs.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StrengthenGraphs.java @@ -284,6 +284,7 @@ public void simplify(Node n, SimplifierTool tool) { } private void handleInvoke(Invoke invoke, SimplifierTool tool) { + PointsToAnalysis bb = ((PointsToAnalysis) getBigBang()); FixedNode node = invoke.asFixedNode(); MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); @@ -416,6 +417,7 @@ private void devirtualizeInvoke(AnalysisMethod singleCallee, Invoke invoke) { } private boolean isUnreachable(Node branch) { + PointsToAnalysis bb = ((PointsToAnalysis) getBigBang()); TypeFlow branchFlow = originalFlows.getNodeFlows().get(branch); return branchFlow != null && !methodFlow.isSaturated(bb, branchFlow) && @@ -468,6 +470,7 @@ private PiNode insertPi(ValueNode input, Stamp piStamp, FixedWithNextNode anchor } private Stamp strengthenStampFromTypeFlow(ValueNode node, TypeFlow nodeFlow, FixedWithNextNode anchorPoint, SimplifierTool tool) { + PointsToAnalysis bb = ((PointsToAnalysis) getBigBang()); if (node.getStackKind() != JavaKind.Object) { return null; } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java new file mode 100644 index 000000000000..2d6df1ac45d4 --- /dev/null +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.reachability; + +import com.oracle.graal.pointsto.meta.AnalysisMethod; +import com.oracle.graal.pointsto.meta.AnalysisType; + +public class MethodSummary { + public final AnalysisMethod[] invokedMethods; + public final AnalysisType[] instantiatedTypes; + + public MethodSummary(AnalysisMethod[] invokedMethods, AnalysisType[] instantiatedTypes) { + this.invokedMethods = invokedMethods; + this.instantiatedTypes = instantiatedTypes; + } +} diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummaryProvider.java new file mode 100644 index 000000000000..17a29c93253a --- /dev/null +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummaryProvider.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.reachability; + +import com.oracle.graal.pointsto.meta.AnalysisMethod; + +public interface MethodSummaryProvider { + MethodSummary getSummary(AnalysisMethod method); +} diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index 14e2ea13baac..82ecbf94d6b1 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -36,27 +36,35 @@ import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.options.OptionValues; -import java.lang.reflect.Executable; +import java.util.Set; import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.TimeUnit; import static jdk.vm.ci.common.JVMCIError.shouldNotReachHere; public abstract class ReachabilityAnalysis extends AbstractReachabilityAnalysis { + private final MethodSummaryProvider methodSummaryProvider; + private final AnalysisType objectType; + public ReachabilityAnalysis(OptionValues options, AnalysisUniverse universe, HostedProviders providers, HostVM hostVM, ForkJoinPool executorService, Runnable heartbeatCallback, - UnsupportedFeatures unsupportedFeatures) { + UnsupportedFeatures unsupportedFeatures, MethodSummaryProvider methodSummaryProvider) { super(options, universe, providers, hostVM, executorService, heartbeatCallback, unsupportedFeatures); + this.methodSummaryProvider = methodSummaryProvider; + this.objectType = metaAccess.lookupJavaType(Object.class); } @Override public AnalysisType addRootClass(AnalysisType type, boolean addFields, boolean addArrayClass) { - // todo async try (Indent indent = debug.logAndIndent("add root class %s", type.getName())) { for (AnalysisField field : type.getInstanceFields(false)) { if (addFields) { field.registerAsAccessed(); } } + + markTypeInstantiated(type); + if (type.getSuperclass() != null) { addRootClass(type.getSuperclass(), addFields, addArrayClass); } @@ -69,7 +77,6 @@ public AnalysisType addRootClass(AnalysisType type, boolean addFields, boolean a @Override public AnalysisType addRootField(Class clazz, String fieldName) { - // todo async AnalysisType type = addRootClass(clazz, false, false); for (AnalysisField field : type.getInstanceFields(true)) { if (field.getName().equals(fieldName)) { @@ -83,17 +90,73 @@ public AnalysisType addRootField(Class clazz, String fieldName) { } @Override - public AnalysisMethod addRootMethod(AnalysisMethod aMethod) { - throw new RuntimeException("unfinished"); + public AnalysisMethod addRootMethod(AnalysisMethod method) { + if (!method.registerAsRootMethod()) { + return method; + } + if (!method.isStatic()) { + markTypeInstantiated(method.getDeclaringClass()); + } + markMethodImplementationInvoked(method); + return method; } - @Override - public AnalysisMethod addRootMethod(Executable method) { - throw new RuntimeException("unfinished"); + private void markMethodImplementationInvoked(AnalysisMethod method) { + if (!method.registerAsImplementationInvoked(null)) { + return; + } + schedule(() -> onMethodImplementationInvoked(method)); + } + + private void onMethodImplementationInvoked(AnalysisMethod method) { + MethodSummary summary = methodSummaryProvider.getSummary(method); + for (AnalysisMethod invokedMethod : summary.invokedMethods) { + markMethodInvoked(invokedMethod); + } + for (AnalysisType type : summary.instantiatedTypes) { + markTypeInstantiated(type); + } + } + + private void markTypeInstantiated(AnalysisType type) { + if (!type.registerAsAllocated(null)) { + return; + } + AnalysisType current = type; + while (current != null) { + Set invokedMethods = current.getInvokedMethods(); + for (AnalysisMethod method : invokedMethods) { + AnalysisMethod implementationInvokedMethod = type.resolveMethod(method, current); + markMethodImplementationInvoked(implementationInvokedMethod); + } + current = current.getSuperclass(); + } + } + + private void markMethodInvoked(AnalysisMethod method) { + if (!method.registerAsInvoked(null)) { + return; + } + schedule(() -> onMethodInvoked(method)); + } + + private void onMethodInvoked(AnalysisMethod method) { + AnalysisType clazz = method.getDeclaringClass(); + Set instantiatedSubtypes = clazz.getInstantiatedSubtypes(); + for (AnalysisType subtype : instantiatedSubtypes) { + AnalysisMethod resolvedMethod = subtype.resolveMethod(method, clazz); + markMethodImplementationInvoked(resolvedMethod); + } } @Override public boolean finish() throws InterruptedException { + while (true) { + boolean quiescent = executorService.awaitQuiescence(100, TimeUnit.MILLISECONDS); + if (quiescent) { + break; + } + } return false; } @@ -104,16 +167,16 @@ public void cleanupAfterAnalysis() { @Override public void forceUnsafeUpdate(AnalysisField field) { - throw new RuntimeException("unfinished"); + // todo what to do? } @Override public void registerAsJNIAccessed(AnalysisField field, boolean writable) { - throw new RuntimeException("unfinished"); + // todo what to do? } @Override public TypeState getAllSynchronizedTypeState() { - throw new RuntimeException("unfinished"); + return objectType.getTypeFlow(this, true).getState(); } } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java new file mode 100644 index 000000000000..04020c224dc2 --- /dev/null +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.reachability; + +import com.oracle.graal.pointsto.meta.AnalysisMethod; +import org.graalvm.compiler.graph.Node; + +public class SimpleInMemoryMethodSummaryProvider implements MethodSummaryProvider { + @Override + public MethodSummary getSummary(AnalysisMethod method) { + for (Node node : method.getAnalyzedGraph().getNodes()) { + + } + throw new RuntimeException("unfinished"); + } +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java index 9ecdd04255b7..916d5cf5a502 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java @@ -31,6 +31,9 @@ import java.util.Set; import java.util.concurrent.ForkJoinPool; +import com.oracle.graal.pointsto.BigBang; +import com.oracle.graal.pointsto.results.DummyResultsBuilder; +import com.oracle.svm.hosted.analysis.Inflation; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.debug.DebugContext; @@ -183,7 +186,8 @@ public AbstractAnalysisResultsBuilder createStaticAnalysisResultsBuilder(Inflati } } else { /*- A custom result builder for Reachability analysis will probably have to be created */ - throw VMError.shouldNotReachHere("Unsupported analysis type: " + bb.getClass()); + // todo better profiles? + return new DummyResultsBuilder(bb, universe); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index 2a1146463534..9bbf039642e2 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -56,6 +56,11 @@ import java.util.function.BooleanSupplier; import java.util.stream.Collectors; +import com.oracle.graal.pointsto.PointsToAnalysis; +import com.oracle.graal.pointsto.meta.PointsToAnalysisFactory; +import com.oracle.graal.pointsto.meta.PointsToAnalysisMethod; +import com.oracle.graal.reachability.SimpleInMemoryMethodSummaryProvider; +import com.oracle.svm.hosted.analysis.NativeImageReachabilityAnalysis; import org.graalvm.collections.EconomicSet; import org.graalvm.collections.Pair; import org.graalvm.compiler.api.replacements.Fold; @@ -1002,8 +1007,11 @@ public static void initializeBigBang(Inflation bb, OptionValues options, Feature bb.getAnnotationSubstitutionProcessor(), classInitializationPlugin, bb.getHostVM().getClassInitializationSupport(), ConfigurationValues.getTarget()); registerReplacements(debug, featureHandler, null, aProviders, true, initForeignCalls); - for (StructuredGraph graph : aReplacements.getSnippetGraphs(GraalOptions.TrackNodeSourcePosition.getValue(options), options)) { - HostedConfiguration.instance().createMethodTypeFlowBuilder(((NativeImagePointsToAnalysis) bb), graph).registerUsedElements(false); + if (bb instanceof NativeImagePointsToAnalysis) { + // todo refactor + for (StructuredGraph graph : aReplacements.getSnippetGraphs(GraalOptions.TrackNodeSourcePosition.getValue(options), options)) { + HostedConfiguration.instance().createMethodTypeFlowBuilder(((NativeImagePointsToAnalysis) bb), graph).registerUsedElements(false); + } } } } @@ -1032,6 +1040,9 @@ public static Inflation createBigBang(OptionValues options, TargetDescription ta aProviders = new HostedProviders(aMetaAccess, null, aConstantReflection, aConstantFieldProvider, aForeignCalls, aLoweringProvider, aReplacments, aStampProvider, aSnippetReflection, aWordTypes, platformConfig, aMetaAccessExtensionProvider, originalProviders.getLoopsDataProvider()); + if (NativeImageOptions.UseExperimentalReachabilityAnalysis.getValue()) { + return new NativeImageReachabilityAnalysis(options, aUniverse, aProviders, annotationSubstitutionProcessor, analysisExecutor, heartbeatCallback, new SimpleInMemoryMethodSummaryProvider()); + } return new NativeImagePointsToAnalysis(options, aUniverse, aProviders, annotationSubstitutionProcessor, analysisExecutor, heartbeatCallback, new SubstrateUnsupportedFeatures()); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java index 50a255d37c4a..5a37e87044d4 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java @@ -59,6 +59,9 @@ public class NativeImageOptions { @Option(help = "Overrides CPUFeatures and uses the native architecture, i.e., the architecture of a machine that builds an image. NativeArchitecture takes precedence over CPUFeatures", type = User)// public static final HostedOptionKey NativeArchitecture = new HostedOptionKey<>(false); + @Option(help = "Print information about classes, methods, and fields that are present in the native image")// + public static final HostedOptionKey UseExperimentalReachabilityAnalysis = new HostedOptionKey<>(false); + @Option(help = "Print information about classes, methods, and fields that are present in the native image")// public static final HostedOptionKey PrintUniverse = new HostedOptionKey<>(false); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java new file mode 100644 index 000000000000..e2293b1e4f3a --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.hosted.analysis; + +import com.oracle.graal.pointsto.meta.AnalysisUniverse; +import com.oracle.graal.pointsto.meta.HostedProviders; +import com.oracle.graal.reachability.MethodSummaryProvider; +import com.oracle.graal.reachability.ReachabilityAnalysis; +import com.oracle.graal.reachability.SimpleInMemoryMethodSummaryProvider; +import com.oracle.svm.core.graal.meta.SubstrateReplacements; +import com.oracle.svm.hosted.SVMHost; +import com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor; +import org.graalvm.compiler.options.OptionValues; + +import java.util.concurrent.ForkJoinPool; + +public class NativeImageReachabilityAnalysis extends ReachabilityAnalysis implements Inflation { + + private final AnnotationSubstitutionProcessor annotationSubstitutionProcessor; + + public NativeImageReachabilityAnalysis(OptionValues options, AnalysisUniverse universe, HostedProviders providers, AnnotationSubstitutionProcessor annotationSubstitutionProcessor, + ForkJoinPool executor, + Runnable heartbeatCallback, MethodSummaryProvider methodSummaryProvider) { + super(options, universe, providers, universe.hostVM(), executor, heartbeatCallback, new SubstrateUnsupportedFeatures(), methodSummaryProvider); + this.annotationSubstitutionProcessor = annotationSubstitutionProcessor; + } + + @Override + public AnnotationSubstitutionProcessor getAnnotationSubstitutionProcessor() { + return annotationSubstitutionProcessor; + } + + @Override + public SubstrateReplacements getReplacements() { + return (SubstrateReplacements) super.getReplacements(); + } + + @Override + public SVMHost getHostVM() { + return (SVMHost) hostVM; + } + + @Override + public void checkUserLimitations() { + // todo + } +} From eda47067489879a65039751fdae6255ca66ab429 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Thu, 23 Sep 2021 15:12:26 +0200 Subject: [PATCH 06/65] continue implementing the reachability analysis, WIP --- .../pointsto/AbstractAnalysisEngine.java | 7 +- .../graal/pointsto/PointsToAnalysis.java | 9 +- .../pointsto/flow/AnalysisParsedGraph.java | 22 +++- .../graal/pointsto/meta/AnalysisMethod.java | 14 +++ .../graal/pointsto/meta/AnalysisType.java | 6 +- .../pointsto/phases/InlineBeforeAnalysis.java | 9 +- .../graal/reachability/MethodSummary.java | 29 ++++- .../reachability/MethodSummaryProvider.java | 3 +- .../reachability/ReachabilityAnalysis.java | 91 +++++++++++--- .../SimpleInMemoryMethodSummaryProvider.java | 111 +++++++++++++++++- .../svm/hosted/NativeImageGenerator.java | 3 +- .../NativeImageReachabilityAnalysis.java | 1 - 12 files changed, 265 insertions(+), 40 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java index fbc2ff2c06bc..61e676419063 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java @@ -34,6 +34,7 @@ import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.graal.pointsto.meta.HostedProviders; import com.oracle.graal.pointsto.reports.StatisticsPrinter; +import com.oracle.graal.pointsto.util.CompletionExecutor; import com.oracle.graal.pointsto.util.Timer; import jdk.vm.ci.meta.ConstantReflectionProvider; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; @@ -65,6 +66,7 @@ public abstract class AbstractAnalysisEngine implements BigBang { private final List debugHandlerFactories; private final HeapScanningPolicy heapScanningPolicy; private final Replacements replacements; + protected final CompletionExecutor executor; public AbstractAnalysisEngine(OptionValues options, AnalysisUniverse universe, HostedProviders providers, HostVM hostVM, ForkJoinPool executorService, Runnable heartbeatCallback, UnsupportedFeatures unsupportedFeatures) { @@ -76,6 +78,8 @@ public AbstractAnalysisEngine(OptionValues options, AnalysisUniverse universe, H this.providers = providers; this.hostVM = hostVM; this.executorService = executorService; + this.executor = new CompletionExecutor(this, executorService, heartbeatCallback); + this.executor.init(null); this.heartbeatCallback = heartbeatCallback; this.unsupportedFeatures = unsupportedFeatures; this.replacements = providers.getReplacements(); @@ -197,7 +201,8 @@ public HostVM getHostVM() { } protected void schedule(Runnable task) { - executorService.submit(task); + executor.execute((d) -> task.run()); + // executorService.submit(task); } @Override diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java index 08d9776ec0b1..c261541fcffd 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java @@ -741,7 +741,14 @@ private boolean analysisModified() throws InterruptedException { @SuppressFBWarnings(value = "NP_NONNULL_PARAM_VIOLATION", justification = "ForkJoinPool does support null for the exception handler.") public static ForkJoinPool createExecutor(DebugContext debug, int numberOfThreads) { ForkJoinPool.ForkJoinWorkerThreadFactory factory = debugThreadFactory(debug.areScopesEnabled() || debug.areMetricsEnabled() ? debug : null); - return new ForkJoinPool(numberOfThreads, factory, null, false); + return new ForkJoinPool(numberOfThreads, factory, new Thread.UncaughtExceptionHandler() { + @Override + public void uncaughtException(Thread t, Throwable e) { + System.err.println("Thread " + t); + e.printStackTrace(); + System.err.println("---"); + } + }, false); } private static ForkJoinPool.ForkJoinWorkerThreadFactory debugThreadFactory(DebugContext debug) { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/AnalysisParsedGraph.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/AnalysisParsedGraph.java index 8665d25fab08..dfa7ad642b56 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/AnalysisParsedGraph.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/AnalysisParsedGraph.java @@ -24,6 +24,7 @@ */ package com.oracle.graal.pointsto.flow; +import com.oracle.graal.pointsto.meta.HostedProviders; import org.graalvm.compiler.api.runtime.GraalJVMCICompiler; import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; @@ -38,6 +39,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.printer.GraalDebugHandlersFactory; @@ -101,13 +103,21 @@ public static AnalysisParsedGraph parseBytecode(BigBang bb, AnalysisMethod metho return optimizeAndEncode(bb, method, graph, false); } - InvocationPlugin plugin = bb.getProviders().getGraphBuilderPlugins().getInvocationPlugins().lookupInvocation(method); - if (plugin != null && !plugin.inlineOnly()) { - Bytecode code = new ResolvedJavaMethodBytecode(method); - graph = new SubstrateIntrinsicGraphBuilder(options, debug, bb.getProviders(), code).buildGraph(plugin); - if (graph != null) { - return optimizeAndEncode(bb, method, graph, true); + HostedProviders providers = bb.getProviders(); + GraphBuilderConfiguration.Plugins graphBuilderPlugins = providers.getGraphBuilderPlugins(); + if (graphBuilderPlugins != null) { + InvocationPlugins invocationPlugins = graphBuilderPlugins.getInvocationPlugins(); + InvocationPlugin plugin = invocationPlugins.lookupInvocation(method); + if (plugin != null && !plugin.inlineOnly()) { + Bytecode code = new ResolvedJavaMethodBytecode(method); + graph = new SubstrateIntrinsicGraphBuilder(options, debug, bb.getProviders(), code).buildGraph(plugin); + if (graph != null) { + return optimizeAndEncode(bb, method, graph, true); + } } + } else { + // todo what to do? + System.err.println("errr??"); } if (method.getCode() == null) { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java index 3cbf3df0450e..ace670ffa3fc 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java @@ -32,6 +32,7 @@ import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.util.Collection; +import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; @@ -101,6 +102,8 @@ public abstract class AnalysisMethod implements WrappedJavaMethod, GraphProvider */ protected AnalysisMethod[] implementations; + private Object reason; + public AnalysisMethod(AnalysisUniverse universe, ResolvedJavaMethod wrapped) { this.wrapped = wrapped; this.id = universe.nextMethodId.getAndIncrement(); @@ -619,4 +622,15 @@ public StructuredGraph getAnalyzedGraph() { public void setAnalyzedGraph(StructuredGraph analyzedGraph) { this.analyzedGraph = analyzedGraph; } + + public void setReason(Object reason) { + this.reason = reason; + } + + public String getReason() { + if (reason instanceof StackTraceElement[]) { + return Arrays.toString(((StackTraceElement[]) reason)); + } + return reason.toString(); + } } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java index 7036b9deface..30d977a9b0a8 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java @@ -797,7 +797,8 @@ public int getModifiers() { @Override public boolean isAssignableFrom(ResolvedJavaType other) { - ResolvedJavaType subst = universe.substitutions.resolve(((AnalysisType) other).wrapped); + AnalysisType analysisOther = other instanceof AnalysisType ? ((AnalysisType) other) : universe.lookup(other); + ResolvedJavaType subst = universe.substitutions.resolve(analysisOther.wrapped); return wrapped.isAssignableFrom(subst); } @@ -836,7 +837,8 @@ private void addSubType(AnalysisType subType) { @Override public AnalysisType findLeastCommonAncestor(ResolvedJavaType otherType) { - ResolvedJavaType subst = universe.substitutions.resolve(((AnalysisType) otherType).wrapped); + AnalysisType analysisOther = otherType instanceof AnalysisType ? (AnalysisType) otherType : universe.lookup(otherType); + ResolvedJavaType subst = universe.substitutions.resolve(analysisOther.wrapped); return universe.lookup(wrapped.findLeastCommonAncestor(subst)); } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysis.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysis.java index 5e6874405637..4da18e1fb81e 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysis.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysis.java @@ -28,6 +28,7 @@ import java.util.Deque; import java.util.concurrent.ConcurrentHashMap; +import com.oracle.graal.pointsto.BigBang; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; @@ -82,7 +83,7 @@ public static class Options { } @SuppressWarnings("try") - public static StructuredGraph decodeGraph(PointsToAnalysis bb, AnalysisMethod method, AnalysisParsedGraph analysisParsedGraph) { + public static StructuredGraph decodeGraph(BigBang bb, AnalysisMethod method, AnalysisParsedGraph analysisParsedGraph) { DebugContext.Description description = new DebugContext.Description(method, ClassUtil.getUnqualifiedName(method.getClass()) + ":" + method.getId()); DebugContext debug = new DebugContext.Builder(bb.getOptions(), new GraalDebugHandlersFactory(bb.getProviders().getSnippetReflection())).description(description).build(); @@ -94,7 +95,7 @@ public static StructuredGraph decodeGraph(PointsToAnalysis bb, AnalysisMethod me try (DebugContext.Scope s = debug.scope("InlineBeforeAnalysis", result)) { - if (bb.strengthenGraalGraphs() && Options.InlineBeforeAnalysis.getValue(bb.getOptions())) { + if (((bb instanceof PointsToAnalysis) && ((PointsToAnalysis) bb).strengthenGraalGraphs()) && Options.InlineBeforeAnalysis.getValue(bb.getOptions())) { InlineBeforeAnalysisGraphDecoder decoder = new InlineBeforeAnalysisGraphDecoder<>(bb, bb.getHostVM().inlineBeforeAnalysisPolicy(), result); decoder.decode(method, false, result.trackNodeSourcePosition()); } else { @@ -152,10 +153,10 @@ class InlineBeforeAnalysisMethodScope extends PEMethodScope { } } - private final PointsToAnalysis bb; + private final BigBang bb; private final InlineBeforeAnalysisPolicy policy; - InlineBeforeAnalysisGraphDecoder(PointsToAnalysis bb, InlineBeforeAnalysisPolicy policy, StructuredGraph graph) { + InlineBeforeAnalysisGraphDecoder(BigBang bb, InlineBeforeAnalysisPolicy policy, StructuredGraph graph) { super(AnalysisParsedGraph.HOST_ARCHITECTURE, graph, bb.getProviders(), null, bb.getProviders().getGraphBuilderPlugins().getInvocationPlugins(), new InlineInvokePlugin[]{new InlineBeforeAnalysisInlineInvokePlugin(policy)}, diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java index 2d6df1ac45d4..bb0cce821f42 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java @@ -24,15 +24,42 @@ */ package com.oracle.graal.reachability; +import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.graal.pointsto.meta.AnalysisType; +import jdk.vm.ci.meta.JavaConstant; + +import java.util.Arrays; public class MethodSummary { + public static final MethodSummary EMPTY = new MethodSummary(new AnalysisMethod[0], new AnalysisMethod[0], new AnalysisType[0], new AnalysisType[0], new AnalysisField[0], new JavaConstant[0]); + public final AnalysisMethod[] invokedMethods; + public final AnalysisMethod[] implementationInvokedMethods; + public final AnalysisType[] accessedTypes; public final AnalysisType[] instantiatedTypes; + public final AnalysisField[] accessedFields; + public final JavaConstant[] embeddedConstants; - public MethodSummary(AnalysisMethod[] invokedMethods, AnalysisType[] instantiatedTypes) { + public MethodSummary(AnalysisMethod[] invokedMethods, AnalysisMethod[] implementationInvokedMethods, AnalysisType[] accessedTypes, AnalysisType[] instantiatedTypes, AnalysisField[] accessedFields, + JavaConstant[] embeddedConstants) { this.invokedMethods = invokedMethods; + this.implementationInvokedMethods = implementationInvokedMethods; + this.accessedTypes = accessedTypes; this.instantiatedTypes = instantiatedTypes; + this.accessedFields = accessedFields; + this.embeddedConstants = embeddedConstants; + } + + @Override + public String toString() { + return "MethodSummary{" + + "invokedMethods=" + Arrays.toString(invokedMethods) + + "implementationInvokedMethods=" + Arrays.toString(implementationInvokedMethods) + + ", accessedTypes=" + Arrays.toString(accessedTypes) + + ", instantiatedTypes=" + Arrays.toString(instantiatedTypes) + + ", accessedFields=" + Arrays.toString(accessedFields) + + ", embeddedConstants=" + Arrays.toString(embeddedConstants) + + '}'; } } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummaryProvider.java index 17a29c93253a..710576e71db5 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummaryProvider.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummaryProvider.java @@ -24,8 +24,9 @@ */ package com.oracle.graal.reachability; +import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.meta.AnalysisMethod; public interface MethodSummaryProvider { - MethodSummary getSummary(AnalysisMethod method); + MethodSummary getSummary(BigBang bigBang, AnalysisMethod method); } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index 82ecbf94d6b1..b1b75b34234d 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -33,12 +33,14 @@ import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.graal.pointsto.meta.HostedProviders; import com.oracle.graal.pointsto.typestate.TypeState; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.options.OptionValues; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.TimeUnit; import static jdk.vm.ci.common.JVMCIError.shouldNotReachHere; @@ -97,27 +99,73 @@ public AnalysisMethod addRootMethod(AnalysisMethod method) { if (!method.isStatic()) { markTypeInstantiated(method.getDeclaringClass()); } - markMethodImplementationInvoked(method); + markMethodImplementationInvoked(method, new RuntimeException().getStackTrace()); return method; } - private void markMethodImplementationInvoked(AnalysisMethod method) { + private void markMethodImplementationInvoked(AnalysisMethod method, Object reason) { if (!method.registerAsImplementationInvoked(null)) { return; } + method.setReason(reason); schedule(() -> onMethodImplementationInvoked(method)); } + private static final Set processed = ConcurrentHashMap.newKeySet(); + private static final Set processed2 = ConcurrentHashMap.newKeySet(); + private void onMethodImplementationInvoked(AnalysisMethod method) { - MethodSummary summary = methodSummaryProvider.getSummary(method); - for (AnalysisMethod invokedMethod : summary.invokedMethods) { - markMethodInvoked(invokedMethod); + if (!processed.add(method)) { +// System.err.println("Method " + method + " has already been processed"); + return; } - for (AnalysisType type : summary.instantiatedTypes) { - markTypeInstantiated(type); + if (!processed2.add(method.getQualifiedName())) { +// System.err.println("Method " + method + " has already been processed"); + return; + } + if (method.isNative()) { + return; + } + try { + MethodSummary summary = methodSummaryProvider.getSummary(this, method); + for (AnalysisMethod invokedMethod : summary.invokedMethods) { + markMethodInvoked(invokedMethod); + } + for (AnalysisMethod invokedMethod : summary.implementationInvokedMethods) { + markMethodImplementationInvoked(invokedMethod, method); + } + for (AnalysisType type : summary.accessedTypes) { + markTypeAccessed(type); + } + for (AnalysisType type : summary.instantiatedTypes) { + markTypeInstantiated(type); + } + for (AnalysisField field : summary.accessedFields) { + markFieldAccessed(field); + } + for (JavaConstant constant : summary.embeddedConstants) { + if (constant.getJavaKind() == JavaKind.Object && constant.isNonNull()) { + // todo heap initiate scanning + markTypeInstantiated(metaAccess.lookupJavaType(constant.getClass())); + } + } + } catch (Throwable ex) { + System.err.println("Failed to provide a summary for " + method.format("%H.%n(%p)")); + System.err.println(ex + " " + ex.getMessage()); + System.err.println("Parsing reason: " + method.getReason()); + ex.printStackTrace(); } } + private void markFieldAccessed(AnalysisField field) { + field.registerAsAccessed(); + } + + private void markTypeAccessed(AnalysisType type) { + // todo double check whether all necessary logic is in + type.registerAsReachable(); + } + private void markTypeInstantiated(AnalysisType type) { if (!type.registerAsAllocated(null)) { return; @@ -126,8 +174,9 @@ private void markTypeInstantiated(AnalysisType type) { while (current != null) { Set invokedMethods = current.getInvokedMethods(); for (AnalysisMethod method : invokedMethods) { - AnalysisMethod implementationInvokedMethod = type.resolveMethod(method, current); - markMethodImplementationInvoked(implementationInvokedMethod); + AnalysisMethod implementationInvokedMethod = type.resolveConcreteMethod(method, current); + markMethodImplementationInvoked(implementationInvokedMethod, type); // todo better + // reason } current = current.getSuperclass(); } @@ -144,20 +193,25 @@ private void onMethodInvoked(AnalysisMethod method) { AnalysisType clazz = method.getDeclaringClass(); Set instantiatedSubtypes = clazz.getInstantiatedSubtypes(); for (AnalysisType subtype : instantiatedSubtypes) { - AnalysisMethod resolvedMethod = subtype.resolveMethod(method, clazz); - markMethodImplementationInvoked(resolvedMethod); + AnalysisMethod resolvedMethod = subtype.resolveConcreteMethod(method, clazz); + markMethodImplementationInvoked(resolvedMethod, method); // todo better reason } } @Override public boolean finish() throws InterruptedException { - while (true) { - boolean quiescent = executorService.awaitQuiescence(100, TimeUnit.MILLISECONDS); - if (quiescent) { - break; - } + if (!executor.isStarted()) { + executor.start(); } - return false; + executor.complete(); + return true; +// while (true) { +// boolean quiescent = executorService.awaitQuiescence(100, TimeUnit.MILLISECONDS); +// if (quiescent) { +// break; +// } +// } +// return false; } @Override @@ -177,6 +231,7 @@ public void registerAsJNIAccessed(AnalysisField field, boolean writable) { @Override public TypeState getAllSynchronizedTypeState() { + // todo don't overapproximate so much return objectType.getTypeFlow(this, true).getState(); } } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java index 04020c224dc2..7d5faa7d1b8a 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java @@ -24,15 +24,118 @@ */ package com.oracle.graal.reachability; +import com.oracle.graal.pointsto.BigBang; +import com.oracle.graal.pointsto.flow.AnalysisParsedGraph; +import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisMethod; +import com.oracle.graal.pointsto.meta.AnalysisType; +import com.oracle.graal.pointsto.meta.AnalysisUniverse; +import com.oracle.graal.pointsto.phases.InlineBeforeAnalysis; +import com.oracle.graal.pointsto.util.AnalysisError; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.ResolvedJavaType; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.nodes.CallTargetNode; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.Invoke; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.java.AccessFieldNode; +import org.graalvm.compiler.nodes.java.InstanceOfNode; +import org.graalvm.compiler.nodes.java.NewArrayNode; +import org.graalvm.compiler.nodes.java.NewInstanceNode; +import org.graalvm.compiler.nodes.java.NewMultiArrayNode; +import org.graalvm.util.GuardedAnnotationAccess; + +import java.util.ArrayList; +import java.util.List; public class SimpleInMemoryMethodSummaryProvider implements MethodSummaryProvider { - @Override - public MethodSummary getSummary(AnalysisMethod method) { - for (Node node : method.getAnalyzedGraph().getNodes()) { + private final AnalysisUniverse universe; + + public SimpleInMemoryMethodSummaryProvider(AnalysisUniverse universe) { + this.universe = universe; + } + + @Override + public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { + // todo clean this up +// System.out.println("Making a summary for " + method.format("%H.%n(%p)")); +// System.out.println("1 Analyzed graph: " + method.getAnalyzedGraph()); + if (method.isIntrinsicMethod()) { + System.err.println("this is intrinsic: " + method); + return MethodSummary.EMPTY; + } + AnalysisParsedGraph analysisParsedGraph = method.ensureGraphParsed(bb); + if (analysisParsedGraph.getEncodedGraph() == null) { + System.err.println("Encoded empty for " + method); + return MethodSummary.EMPTY; + } + if (GuardedAnnotationAccess.isAnnotationPresent(method, Node.NodeIntrinsic.class)) { + System.err.println("parsing an intrinsic: " + method); + return MethodSummary.EMPTY; + } +// System.out.println("2 Analyzed graph: " + method.getAnalyzedGraph()); +// System.out.println("analysis parsed graph " + analysisParsedGraph); +// System.out.println("Encoded graph " + analysisParsedGraph.getEncodedGraph()); + StructuredGraph decoded = InlineBeforeAnalysis.decodeGraph(bb, method, analysisParsedGraph); +// StructuredGraph decoded = analysisParsedGraph.graph; +// System.out.println("decoded " + decoded); + if (decoded == null) { + throw AnalysisError.shouldNotReachHere("Failed to decode a graph for " + method.format("%H.%n(%p)")); + } + List accessedTypes = new ArrayList<>(); + List instantiatedTypes = new ArrayList<>(); + List accessedFields = new ArrayList<>(); + List invokedMethods = new ArrayList<>(); + List implementationInvokedMethods = new ArrayList<>(); + List embeddedConstants = new ArrayList<>(); + for (Node n : decoded.getNodes()) { + if (n instanceof NewInstanceNode) { + NewInstanceNode node = (NewInstanceNode) n; + instantiatedTypes.add(universe.lookup(node.instanceClass())); + } else if (n instanceof NewArrayNode) { + NewArrayNode node = (NewArrayNode) n; + instantiatedTypes.add(universe.lookup(node.elementType()).getArrayClass()); + } else if (n instanceof NewMultiArrayNode) { + NewMultiArrayNode node = (NewMultiArrayNode) n; + ResolvedJavaType type = node.type(); + for (int i = 0; i < node.dimensionCount(); i++) { + instantiatedTypes.add(universe.lookup(type)); + type = type.getComponentType(); + } + } else if (n instanceof ConstantNode) { + ConstantNode node = (ConstantNode) n; + if (!(node.getValue() instanceof JavaConstant)) { + /* + * The bytecode parser sometimes embeds low-level VM constants for types into + * the high-level graph. Since these constants are the result of type lookups, + * these types are already marked as reachable. Eventually, the bytecode parser + * should be changed to only use JavaConstant. + */ + continue; + } + embeddedConstants.add(((JavaConstant) node.getValue())); + } else if (n instanceof InstanceOfNode) { + InstanceOfNode node = (InstanceOfNode) n; + accessedTypes.add(universe.lookup(node.type().getType())); + } else if (n instanceof AccessFieldNode) { + AccessFieldNode node = (AccessFieldNode) n; + accessedFields.add(universe.lookup(node.field())); + } else if (n instanceof Invoke) { + Invoke node = (Invoke) n; + CallTargetNode.InvokeKind kind = node.getInvokeKind(); + if (kind.isDirect()) { + implementationInvokedMethods.add(universe.lookup(node.getTargetMethod())); + } else { + invokedMethods.add(universe.lookup(node.getTargetMethod())); + } + } } - throw new RuntimeException("unfinished"); + MethodSummary summary = new MethodSummary(invokedMethods.toArray(new AnalysisMethod[0]), implementationInvokedMethods.toArray(new AnalysisMethod[0]), + accessedTypes.toArray(new AnalysisType[0]), + instantiatedTypes.toArray(new AnalysisType[0]), accessedFields.toArray(new AnalysisField[0]), embeddedConstants.toArray(new JavaConstant[0])); +// System.out.println("Made a summary " + summary); + return summary; } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index 9bbf039642e2..f32a69350b5c 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -1041,7 +1041,8 @@ public static Inflation createBigBang(OptionValues options, TargetDescription ta aSnippetReflection, aWordTypes, platformConfig, aMetaAccessExtensionProvider, originalProviders.getLoopsDataProvider()); if (NativeImageOptions.UseExperimentalReachabilityAnalysis.getValue()) { - return new NativeImageReachabilityAnalysis(options, aUniverse, aProviders, annotationSubstitutionProcessor, analysisExecutor, heartbeatCallback, new SimpleInMemoryMethodSummaryProvider()); + return new NativeImageReachabilityAnalysis(options, aUniverse, aProviders, annotationSubstitutionProcessor, analysisExecutor, heartbeatCallback, + new SimpleInMemoryMethodSummaryProvider(aUniverse)); } return new NativeImagePointsToAnalysis(options, aUniverse, aProviders, annotationSubstitutionProcessor, analysisExecutor, heartbeatCallback, new SubstrateUnsupportedFeatures()); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java index e2293b1e4f3a..ec3ad0608029 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java @@ -28,7 +28,6 @@ import com.oracle.graal.pointsto.meta.HostedProviders; import com.oracle.graal.reachability.MethodSummaryProvider; import com.oracle.graal.reachability.ReachabilityAnalysis; -import com.oracle.graal.reachability.SimpleInMemoryMethodSummaryProvider; import com.oracle.svm.core.graal.meta.SubstrateReplacements; import com.oracle.svm.hosted.SVMHost; import com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor; From 0bbbd40044abdddcf7c9f2d3a3429a50d51c8405 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Tue, 28 Sep 2021 19:47:41 +0200 Subject: [PATCH 07/65] more fixes --- .../hosted/ameta/AnalysisConstantReflectionProvider.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java index a5b0c98f8537..baacc6302df5 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java @@ -98,7 +98,11 @@ public JavaConstant readValue(MetaAccessProvider suppliedMetaAccess, AnalysisFie throw VMError.shouldNotReachHere("Cannot read instance field of a class that is initialized at run time: " + field.format("%H.%n")); } } else { - value = universe.lookup(ReadableJavaField.readFieldValue(suppliedMetaAccess, originalConstantReflection, field.wrapped, universe.toHosted(receiver))); + ResolvedJavaField current = field; + while (current instanceof AnalysisField) { + current = ((AnalysisField) current).wrapped; + } + value = universe.lookup(ReadableJavaField.readFieldValue(suppliedMetaAccess, originalConstantReflection, current, universe.toHosted(receiver))); } return interceptValue(field, value); From bd5a928da620e6eb0b1954f226034c4fb9e05289 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Fri, 1 Oct 2021 17:16:10 +0200 Subject: [PATCH 08/65] implementation in progress --- .../pointsto/AbstractAnalysisEngine.java | 2 +- .../graal/pointsto/PointsToAnalysis.java | 21 +++++ .../graal/pointsto/ReachabilityAnalysis.java | 39 ++++++++++ .../graal/pointsto/meta/AnalysisType.java | 9 ++- .../graal/pointsto/meta/AnalysisUniverse.java | 12 +++ .../reachability/ReachabilityAnalysis.java | 77 ++++++++++++++++--- .../ReachabilityObjectScanner.java | 68 ++++++++++++++++ .../SimpleInMemoryMethodSummaryProvider.java | 39 +++++++--- .../com/oracle/svm/hosted/FeatureImpl.java | 46 ++++++++--- .../svm/hosted/NativeImageGenerator.java | 3 + .../oracle/svm/hosted/code/CompileQueue.java | 1 + .../svm/hosted/meta/HostedUniverse.java | 9 +++ 12 files changed, 296 insertions(+), 30 deletions(-) create mode 100644 substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityObjectScanner.java diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java index 61e676419063..1d8daf543bdc 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java @@ -61,7 +61,7 @@ public abstract class AbstractAnalysisEngine implements BigBang { private final Runnable heartbeatCallback; private final UnsupportedFeatures unsupportedFeatures; protected final DebugContext debug; - private final OptionValues options; + protected final OptionValues options; private final AnalysisUniverse universe; private final List debugHandlerFactories; private final HeapScanningPolicy heapScanningPolicy; diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java index c261541fcffd..59763731c772 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java @@ -636,6 +636,27 @@ public boolean finish() throws InterruptedException { } } + @Override + public void markTypeReachable(AnalysisType type) { + type.registerAsReachable(); + } + + @Override + public void markTypeInHeap(AnalysisType type) { + type.registerAsInHeap(); + } + + @Override + public void markFieldAccessed(AnalysisField field) { + field.registerAsAccessed(); + } + + @Override + public void markMethodImplementationInvoked(AnalysisMethod method, Object reason) { + addRootMethod(method).registerAsImplementationInvoked(null); + + } + @SuppressWarnings("try") public boolean doTypeflow() throws InterruptedException { boolean didSomeWork; diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ReachabilityAnalysis.java index 9c84c4c1e817..5aa867756c2e 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ReachabilityAnalysis.java @@ -30,6 +30,7 @@ import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.graal.pointsto.typestate.TypeState; +import com.oracle.svm.util.UnsafePartitionKind; import java.lang.reflect.Executable; @@ -72,6 +73,44 @@ public interface ReachabilityAnalysis { */ AnalysisMethod addRootMethod(Class clazz, String methodName, Class... parameterTypes); + void markTypeReachable(AnalysisType type); + + void markTypeInHeap(AnalysisType type); + + void markFieldAccessed(AnalysisField field); + + default boolean markFieldUnsafeAccessed(AnalysisField field) { + if (!field.isUnsafeAccessed()) { + /* Register the field as unsafe accessed. */ + field.registerAsAccessed(); + field.registerAsUnsafeAccessed(getUniverse()); + /* Force the update of registered unsafe loads and stores. */ + forceUnsafeUpdate(field); + return true; + } + return false; + } + + default void registerAsFrozenUnsafeAccessed(AnalysisField field) { + field.setUnsafeFrozenTypeState(true); + } + + default void registerAsUnsafeAccessed(AnalysisField field, UnsafePartitionKind partitionKind) { + if (!field.isUnsafeAccessed()) { + /* Register the field as unsafe accessed. */ + field.registerAsAccessed(); + field.registerAsUnsafeAccessed(getUniverse(), partitionKind); + /* Force the update of registered unsafe loads and stores. */ + forceUnsafeUpdate(field); + } + } + + default void markFieldRead(AnalysisField field) { + markFieldAccessed(field); + } + + void markMethodImplementationInvoked(AnalysisMethod method, Object reason); + /** * Waits until the analysis is done. */ diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java index 30d977a9b0a8..20774d6fe430 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java @@ -880,7 +880,14 @@ public AnalysisMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType public AnalysisMethod resolveConcreteMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) { Object resolvedMethod = resolvedMethods.get(method); if (resolvedMethod == null) { - ResolvedJavaMethod substMethod = universe.substitutions.resolve(((AnalysisMethod) method).wrapped); + ResolvedJavaMethod current = method; + while (current instanceof AnalysisMethod) { + current = ((AnalysisMethod) current).wrapped; + } + ResolvedJavaMethod substMethod = universe.substitutions.resolve(current); + while (substMethod instanceof AnalysisMethod) { + substMethod = ((AnalysisMethod) substMethod).wrapped; + } /* * We do not want any access checks to be performed, so we use the method's declaring * class as the caller type. diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java index 837d4ba74b12..6d26a775a83c 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java @@ -184,6 +184,10 @@ public AnalysisType optionalLookup(ResolvedJavaType type) { @Override public AnalysisType lookup(JavaType type) { + if (type instanceof AnalysisType) { + System.err.println("Querying already made analysis type: " + type); + return ((AnalysisType) type); + } JavaType result = lookupAllowUnresolved(type); if (result == null) { return null; @@ -343,6 +347,10 @@ public JavaKind getStorageKind(ResolvedJavaType type, MetaAccessProvider metaAcc @Override public AnalysisField lookup(JavaField field) { + if (field instanceof AnalysisField) { + System.err.println("Querying already made analysis type: " + field); + return ((AnalysisField) field); + } JavaField result = lookupAllowUnresolved(field); if (result == null) { return null; @@ -400,6 +408,10 @@ private AnalysisField createField(ResolvedJavaField field) { @Override public AnalysisMethod lookup(JavaMethod method) { + if (method instanceof AnalysisMethod) { + System.err.println("Querying already made analysis method: " + method); + return ((AnalysisMethod) method); + } JavaMethod result = lookupAllowUnresolved(method); if (result == null) { return null; diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index b1b75b34234d..c5db7374883a 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -25,7 +25,9 @@ package com.oracle.graal.reachability; import com.oracle.graal.pointsto.AbstractReachabilityAnalysis; +import com.oracle.graal.pointsto.ObjectScanner; import com.oracle.graal.pointsto.api.HostVM; +import com.oracle.graal.pointsto.api.PointstoOptions; import com.oracle.graal.pointsto.constraints.UnsupportedFeatures; import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisMethod; @@ -33,6 +35,7 @@ import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.graal.pointsto.meta.HostedProviders; import com.oracle.graal.pointsto.typestate.TypeState; +import jdk.vm.ci.code.BytecodePosition; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import org.graalvm.compiler.debug.Indent; @@ -99,11 +102,18 @@ public AnalysisMethod addRootMethod(AnalysisMethod method) { if (!method.isStatic()) { markTypeInstantiated(method.getDeclaringClass()); } + method.registerAsInvoked(null); markMethodImplementationInvoked(method, new RuntimeException().getStackTrace()); return method; } - private void markMethodImplementationInvoked(AnalysisMethod method, Object reason) { + @Override + public void markMethodImplementationInvoked(AnalysisMethod method, Object reason) { + if (method == null) { + System.err.println("Null method received"); + new RuntimeException().printStackTrace(); + return; + } if (!method.registerAsImplementationInvoked(null)) { return; } @@ -124,7 +134,8 @@ private void onMethodImplementationInvoked(AnalysisMethod method) { return; } if (method.isNative()) { - return; + System.err.println("native method " + method); +// return; } try { MethodSummary summary = methodSummaryProvider.getSummary(this, method); @@ -132,10 +143,11 @@ private void onMethodImplementationInvoked(AnalysisMethod method) { markMethodInvoked(invokedMethod); } for (AnalysisMethod invokedMethod : summary.implementationInvokedMethods) { + markMethodInvoked(invokedMethod); markMethodImplementationInvoked(invokedMethod, method); } for (AnalysisType type : summary.accessedTypes) { - markTypeAccessed(type); + markTypeReachable(type); } for (AnalysisType type : summary.instantiatedTypes) { markTypeInstantiated(type); @@ -146,7 +158,15 @@ private void onMethodImplementationInvoked(AnalysisMethod method) { for (JavaConstant constant : summary.embeddedConstants) { if (constant.getJavaKind() == JavaKind.Object && constant.isNonNull()) { // todo heap initiate scanning - markTypeInstantiated(metaAccess.lookupJavaType(constant.getClass())); + // track the constant + if (this.scanningPolicy().trackConstant(this, constant)) { + BytecodePosition position = new BytecodePosition(null, method, 0); + getUniverse().registerEmbeddedRoot(constant, position); + + Object obj = getSnippetReflectionProvider().asObject(Object.class, constant); + AnalysisType type = getMetaAccess().lookupJavaType(obj.getClass()); + markTypeInHeap(type); + } } } } catch (Throwable ex) { @@ -155,18 +175,29 @@ private void onMethodImplementationInvoked(AnalysisMethod method) { System.err.println("Parsing reason: " + method.getReason()); ex.printStackTrace(); } + if (method.getName().contains("VTable")) { + System.out.println("Successfully parsed " + method); + } } - private void markFieldAccessed(AnalysisField field) { + @Override + public void markFieldAccessed(AnalysisField field) { field.registerAsAccessed(); } - private void markTypeAccessed(AnalysisType type) { + @Override + public void markTypeReachable(AnalysisType type) { // todo double check whether all necessary logic is in type.registerAsReachable(); } - private void markTypeInstantiated(AnalysisType type) { + @Override + public void markTypeInHeap(AnalysisType type) { + markTypeInstantiated(type); + type.registerAsInHeap(); + } + + public void markTypeInstantiated(AnalysisType type) { if (!type.registerAsAllocated(null)) { return; } @@ -200,10 +231,16 @@ private void onMethodInvoked(AnalysisMethod method) { @Override public boolean finish() throws InterruptedException { - if (!executor.isStarted()) { - executor.start(); + for (int i = 0; i < 10; i++) { + if (!executor.isStarted()) { + executor.start(); + } + executor.complete(); + executor.shutdown(); + executor.init(); + + checkObjectGraph(); } - executor.complete(); return true; // while (true) { // boolean quiescent = executorService.awaitQuiescence(100, TimeUnit.MILLISECONDS); @@ -214,6 +251,26 @@ public boolean finish() throws InterruptedException { // return false; } + private ObjectScanner.ReusableSet scannedObjects = new ObjectScanner.ReusableSet(); + + @SuppressWarnings("try") + private void checkObjectGraph() throws InterruptedException { + scannedObjects.reset(); + // scan constants + boolean isParallel = PointstoOptions.ScanObjectsParallel.getValue(options); + ObjectScanner objectScanner = new ReachabilityObjectScanner(this, isParallel ? executor : null, scannedObjects, metaAccess); +// checkObjectGraph(objectScanner); + if (isParallel) { + executor.start(); + objectScanner.scanBootImageHeapRoots(null, null); + executor.complete(); + executor.shutdown(); + executor.init(null); + } else { + objectScanner.scanBootImageHeapRoots(null, null); + } + } + @Override public void cleanupAfterAnalysis() { super.cleanupAfterAnalysis(); diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityObjectScanner.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityObjectScanner.java new file mode 100644 index 000000000000..440779fbbc27 --- /dev/null +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityObjectScanner.java @@ -0,0 +1,68 @@ +package com.oracle.graal.reachability; + +import com.oracle.graal.pointsto.BigBang; +import com.oracle.graal.pointsto.ObjectScanner; +import com.oracle.graal.pointsto.meta.AnalysisField; +import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; +import com.oracle.graal.pointsto.meta.AnalysisType; +import com.oracle.graal.pointsto.util.CompletionExecutor; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; + +public class ReachabilityObjectScanner extends ObjectScanner { + + private final AnalysisMetaAccess access; + + public ReachabilityObjectScanner(BigBang bb, CompletionExecutor executor, ReusableSet scannedObjects, AnalysisMetaAccess access) { + super(bb, executor, scannedObjects); + this.access = access; + } + + ReachabilityAnalysis getAnalysis() { + return ((ReachabilityAnalysis) bb); + } + + @Override + public void forRelocatedPointerFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) { + field.registerAsAccessed(); + if (fieldValue.isNonNull() && fieldValue.getJavaKind() == JavaKind.Object) { + // todo mark as instantiated +// getAnalysis().markTypeInstantiated(constantType(bb, fieldValue)); + } + } + + @Override + public void forNullFieldValue(JavaConstant receiver, AnalysisField field) { + if (receiver != null) + getAnalysis().markTypeReachable(constantType(bb, receiver)); + getAnalysis().markTypeReachable(field.getType()); +// System.out.println("Scanning field " + field); + } + + @Override + public void forNonNullFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) { + if (receiver != null) + getAnalysis().markTypeReachable(constantType(bb, receiver)); + getAnalysis().markTypeReachable(field.getType()); +// System.out.println("Scanning field " + field); + } + + @Override + public void forNullArrayElement(JavaConstant array, AnalysisType arrayType, int elementIndex) { + getAnalysis().markTypeReachable(arrayType); + } + + @Override + public void forNonNullArrayElement(JavaConstant array, AnalysisType arrayType, JavaConstant elementConstant, AnalysisType elementType, int elementIndex) { + getAnalysis().markTypeReachable(arrayType); + getAnalysis().markTypeInstantiated(elementType); + } + + @Override + protected void forScannedConstant(JavaConstant scannedValue, ScanReason reason) { + AnalysisType type = constantType(bb, scannedValue); +// System.out.println("Scanning constant of type " + type); + getAnalysis().markTypeInstantiated(type); + type.registerAsInHeap(); + } +} \ No newline at end of file diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java index 7d5faa7d1b8a..a5b09f971ee7 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java @@ -33,6 +33,8 @@ import com.oracle.graal.pointsto.phases.InlineBeforeAnalysis; import com.oracle.graal.pointsto.util.AnalysisError; import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.CallTargetNode; @@ -64,7 +66,7 @@ public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { // System.out.println("1 Analyzed graph: " + method.getAnalyzedGraph()); if (method.isIntrinsicMethod()) { System.err.println("this is intrinsic: " + method); - return MethodSummary.EMPTY; +// return MethodSummary.EMPTY; } AnalysisParsedGraph analysisParsedGraph = method.ensureGraphParsed(bb); if (analysisParsedGraph.getEncodedGraph() == null) { @@ -73,7 +75,7 @@ public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { } if (GuardedAnnotationAccess.isAnnotationPresent(method, Node.NodeIntrinsic.class)) { System.err.println("parsing an intrinsic: " + method); - return MethodSummary.EMPTY; +// return MethodSummary.EMPTY; } // System.out.println("2 Analyzed graph: " + method.getAnalyzedGraph()); // System.out.println("analysis parsed graph " + analysisParsedGraph); @@ -84,6 +86,10 @@ public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { if (decoded == null) { throw AnalysisError.shouldNotReachHere("Failed to decode a graph for " + method.format("%H.%n(%p)")); } + + // to preserve the graphs for compilation + method.setAnalyzedGraph(decoded); + List accessedTypes = new ArrayList<>(); List instantiatedTypes = new ArrayList<>(); List accessedFields = new ArrayList<>(); @@ -93,15 +99,15 @@ public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { for (Node n : decoded.getNodes()) { if (n instanceof NewInstanceNode) { NewInstanceNode node = (NewInstanceNode) n; - instantiatedTypes.add(universe.lookup(node.instanceClass())); + instantiatedTypes.add(analysisType(node.instanceClass())); } else if (n instanceof NewArrayNode) { NewArrayNode node = (NewArrayNode) n; - instantiatedTypes.add(universe.lookup(node.elementType()).getArrayClass()); + instantiatedTypes.add(analysisType(node.elementType()).getArrayClass()); } else if (n instanceof NewMultiArrayNode) { NewMultiArrayNode node = (NewMultiArrayNode) n; ResolvedJavaType type = node.type(); for (int i = 0; i < node.dimensionCount(); i++) { - instantiatedTypes.add(universe.lookup(type)); + instantiatedTypes.add(analysisType(type)); type = type.getComponentType(); } } else if (n instanceof ConstantNode) { @@ -118,17 +124,20 @@ public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { embeddedConstants.add(((JavaConstant) node.getValue())); } else if (n instanceof InstanceOfNode) { InstanceOfNode node = (InstanceOfNode) n; - accessedTypes.add(universe.lookup(node.type().getType())); + accessedTypes.add(analysisType(node.type().getType())); } else if (n instanceof AccessFieldNode) { AccessFieldNode node = (AccessFieldNode) n; - accessedFields.add(universe.lookup(node.field())); + accessedFields.add(analysisField(node.field())); } else if (n instanceof Invoke) { Invoke node = (Invoke) n; CallTargetNode.InvokeKind kind = node.getInvokeKind(); + AnalysisMethod targetMethod = analysisMethod(node.getTargetMethod()); + if (targetMethod == null) + continue; if (kind.isDirect()) { - implementationInvokedMethods.add(universe.lookup(node.getTargetMethod())); + implementationInvokedMethods.add(targetMethod); } else { - invokedMethods.add(universe.lookup(node.getTargetMethod())); + invokedMethods.add(targetMethod); } } } @@ -138,4 +147,16 @@ public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { // System.out.println("Made a summary " + summary); return summary; } + + private AnalysisType analysisType(ResolvedJavaType type) { + return type instanceof AnalysisType ? ((AnalysisType) type) : universe.lookup(type); + } + + private AnalysisMethod analysisMethod(ResolvedJavaMethod method) { + return method instanceof AnalysisMethod ? ((AnalysisMethod) method) : universe.lookup(method); + } + + private AnalysisField analysisField(ResolvedJavaField field) { + return field instanceof AnalysisField ? ((AnalysisField) field) : universe.lookup(field); + } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/FeatureImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/FeatureImpl.java index 26642bc4400d..6f25b7c8a8c2 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/FeatureImpl.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/FeatureImpl.java @@ -337,7 +337,8 @@ public void registerAsUsed(Class clazz) { } public void registerAsUsed(AnalysisType aType) { - aType.registerAsReachable(); + bb.markTypeReachable(aType); +// aType.registerAsReachable(); } @Override @@ -346,17 +347,20 @@ public void registerAsInHeap(Class clazz) { } public void registerAsInHeap(AnalysisType aType) { - aType.registerAsInHeap(); + bb.markTypeInHeap(aType); +// aType.registerAsInHeap(); } @Override public void registerAsAccessed(Field field) { - getMetaAccess().lookupJavaType(field.getDeclaringClass()).registerAsReachable(); + registerAsUsed(getMetaAccess().lookupJavaType(field.getDeclaringClass())); +// getMetaAccess().lookupJavaType(field.getDeclaringClass()).registerAsReachable(); registerAsAccessed(getMetaAccess().lookupJavaField(field)); } public void registerAsAccessed(AnalysisField aField) { - aField.registerAsAccessed(); + bb.markFieldAccessed(aField); +// aField.registerAsAccessed(); } public void registerAsRead(Field field) { @@ -365,12 +369,14 @@ public void registerAsRead(Field field) { } public void registerAsRead(AnalysisField aField) { - aField.registerAsRead(null); + bb.markFieldRead(aField); +// aField.registerAsRead(null); } @Override public void registerAsUnsafeAccessed(Field field) { - getMetaAccess().lookupJavaType(field.getDeclaringClass()).registerAsReachable(); + registerAsUsed(getMetaAccess().lookupJavaType(field.getDeclaringClass())); +// getMetaAccess().lookupJavaType(field.getDeclaringClass()).registerAsReachable(); registerAsUnsafeAccessed(getMetaAccess().lookupJavaField(field)); } @@ -384,15 +390,26 @@ public boolean registerAsUnsafeAccessed(AnalysisField aField) { return true; } return false; +// if (!field.isUnsafeAccessed()) { +// /* Register the field as unsafe accessed. */ +// field.registerAsAccessed(); +// field.registerAsUnsafeAccessed(bb.getUniverse()); +// /* Force the update of registered unsafe loads and stores. */ +// bb.forceUnsafeUpdate(field); +// return true; +// } + return bb.markFieldUnsafeAccessed(aField); } public void registerAsFrozenUnsafeAccessed(Field field) { - getMetaAccess().lookupJavaType(field.getDeclaringClass()).registerAsReachable(); + registerAsUsed(getMetaAccess().lookupJavaType(field.getDeclaringClass())); +// getMetaAccess().lookupJavaType(field.getDeclaringClass()).registerAsReachable(); registerAsFrozenUnsafeAccessed(getMetaAccess().lookupJavaField(field)); } public void registerAsFrozenUnsafeAccessed(AnalysisField aField) { - aField.setUnsafeFrozenTypeState(true); + bb.registerAsFrozenUnsafeAccessed(aField); +// aField.setUnsafeFrozenTypeState(true); registerAsUnsafeAccessed(aField); } @@ -408,6 +425,14 @@ public void registerAsUnsafeAccessed(AnalysisField aField, UnsafePartitionKind p /* Force the update of registered unsafe loads and stores. */ bb.forceUnsafeUpdate(aField); } + bb.registerAsUnsafeAccessed(aField, partitionKind); +// if (!aField.isUnsafeAccessed()) { +// /* Register the field as unsafe accessed. */ +// aField.registerAsAccessed(); +// aField.registerAsUnsafeAccessed(bb.getUniverse(), partitionKind); +// /* Force the update of registered unsafe loads and stores. */ +// bb.forceUnsafeUpdate(aField); +// } } public void registerAsInvoked(Executable method) { @@ -415,7 +440,9 @@ public void registerAsInvoked(Executable method) { } public void registerAsInvoked(AnalysisMethod aMethod) { - bb.addRootMethod(aMethod).registerAsImplementationInvoked(); +// bb.addRootMethod(aMethod).registerAsImplementationInvoked(null); + bb.addRootMethod(aMethod); + bb.markMethodImplementationInvoked(aMethod, null); } public void registerAsCompiled(Executable method) { @@ -428,6 +455,7 @@ public void registerAsCompiled(AnalysisMethod aMethod) { } public void registerUnsafeFieldsRecomputed(Class clazz) { + // todo intercept this as well? getMetaAccess().lookupJavaType(clazz).registerUnsafeFieldsRecomputed(); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index f32a69350b5c..8c7d2aa6370e 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -60,6 +60,7 @@ import com.oracle.graal.pointsto.meta.PointsToAnalysisFactory; import com.oracle.graal.pointsto.meta.PointsToAnalysisMethod; import com.oracle.graal.reachability.SimpleInMemoryMethodSummaryProvider; +import com.oracle.svm.core.code.ImageCodeInfo; import com.oracle.svm.hosted.analysis.NativeImageReachabilityAnalysis; import org.graalvm.collections.EconomicSet; import org.graalvm.collections.Pair; @@ -975,6 +976,8 @@ public static void initializeBigBang(Inflation bb, OptionValues options, Feature bb.addRootClass(CFunctionPointer[].class, false, false).registerAsInHeap(); bb.addRootClass(PointerBase[].class, false, false).registerAsInHeap(); + bb.addRootField(ImageCodeInfo.class, "codeStart"); + try { bb.addRootMethod(SubstrateArraycopySnippets.class.getDeclaredMethod("doArraycopy", Object.class, int.class, Object.class, int.class, int.class)); bb.addRootMethod(Object.class.getDeclaredMethod("getClass")); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java index 26a7220db38c..0de4700a8bb5 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java @@ -1053,6 +1053,7 @@ private void defaultParseFunction(DebugContext debug, HostedMethod method, Compi graph = new StructuredGraph.Builder(getCustomizedOptions(debug), debug).method(method).build(); } } + method.compilationInfo.graph = graph; try (DebugContext.Scope s = debug.scope("Parsing", graph, method, this)) { try { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedUniverse.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedUniverse.java index 2551b7cba9b4..7695ac8ca576 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedUniverse.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedUniverse.java @@ -137,6 +137,11 @@ public HostedType optionalLookup(JavaType type) { @Override public HostedField lookup(JavaField field) { + if (field == null) { + System.err.println("Trying to lookup a field, which is null"); + new RuntimeException().printStackTrace(); + return null; + } JavaField result = lookupAllowUnresolved(field); if (result instanceof ResolvedJavaField) { return (HostedField) result; @@ -159,6 +164,10 @@ public HostedField optionalLookup(JavaField field) { @Override public HostedMethod lookup(JavaMethod method) { + if (method == null) { + System.err.println("Trying to lookup a method, which is null"); + return null; + } JavaMethod result = lookupAllowUnresolved(method); if (result instanceof ResolvedJavaMethod) { return (HostedMethod) result; From c3de5ad404c7cb2d7808406f911a422a2e5f2be5 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Tue, 5 Oct 2021 17:32:55 +0200 Subject: [PATCH 09/65] implementation in progress --- .../pointsto/AbstractAnalysisEngine.java | 21 +++++++++++++++++-- .../graal/pointsto/meta/AnalysisMethod.java | 2 +- .../graal/pointsto/meta/AnalysisUniverse.java | 4 ++++ .../reachability/ReachabilityAnalysis.java | 18 +++++++++------- .../SimpleInMemoryMethodSummaryProvider.java | 12 ++++++++--- .../oracle/svm/hosted/code/CompileQueue.java | 12 +++++++++-- 6 files changed, 53 insertions(+), 16 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java index 1d8daf543bdc..8e284355e3fe 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java @@ -62,11 +62,12 @@ public abstract class AbstractAnalysisEngine implements BigBang { private final UnsupportedFeatures unsupportedFeatures; protected final DebugContext debug; protected final OptionValues options; - private final AnalysisUniverse universe; + protected final AnalysisUniverse universe; private final List debugHandlerFactories; private final HeapScanningPolicy heapScanningPolicy; private final Replacements replacements; protected final CompletionExecutor executor; + protected final AnalysisTiming timing; public AbstractAnalysisEngine(OptionValues options, AnalysisUniverse universe, HostedProviders providers, HostVM hostVM, ForkJoinPool executorService, Runnable heartbeatCallback, UnsupportedFeatures unsupportedFeatures) { @@ -79,7 +80,8 @@ public AbstractAnalysisEngine(OptionValues options, AnalysisUniverse universe, H this.hostVM = hostVM; this.executorService = executorService; this.executor = new CompletionExecutor(this, executorService, heartbeatCallback); - this.executor.init(null); + this.timing = new AnalysisTiming(); + this.executor.init(timing); this.heartbeatCallback = heartbeatCallback; this.unsupportedFeatures = unsupportedFeatures; this.replacements = providers.getReplacements(); @@ -209,4 +211,19 @@ protected void schedule(Runnable task) { public Replacements getReplacements() { return replacements; } + + private class AnalysisTiming extends PointsToAnalysis.BucketTiming { + + @Override + public void printHeader() { + super.printHeader(); + System.out.println(); + } + + @Override + public void print() { + super.print(); + System.out.println(); + } + } } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java index ace670ffa3fc..33db6bf41417 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java @@ -94,7 +94,7 @@ public abstract class AnalysisMethod implements WrappedJavaMethod, GraphProvider private static final Object GRAPH_CACHE_UNPARSED = "unparsed"; private static final Object GRAPH_CACHE_CLEARED = "cleared by cleanupAfterAnalysis"; - private StructuredGraph analyzedGraph; + private volatile StructuredGraph analyzedGraph; /** * All concrete methods that can actually be called when calling this method. This includes all diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java index 6d26a775a83c..d51839e8819d 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java @@ -38,8 +38,10 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; +import com.oracle.graal.pointsto.flow.AnalysisParsedGraph; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.SuppressFBWarnings; +import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.word.WordBase; import com.oracle.graal.pointsto.AnalysisPolicy; @@ -88,6 +90,8 @@ public class AnalysisUniverse implements Universe { private final ConcurrentHashMap embeddedRoots = new ConcurrentHashMap<>(ESTIMATED_EMBEDDED_ROOTS); private final ConcurrentMap unsafeAccessedStaticFields = new ConcurrentHashMap<>(); + public static final ConcurrentMap graphs = new ConcurrentHashMap<>(); + private boolean sealed; private volatile AnalysisType[] typesById = new AnalysisType[ESTIMATED_NUMBER_OF_TYPES]; diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index c5db7374883a..d93963bea462 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -126,16 +126,16 @@ public void markMethodImplementationInvoked(AnalysisMethod method, Object reason private void onMethodImplementationInvoked(AnalysisMethod method) { if (!processed.add(method)) { -// System.err.println("Method " + method + " has already been processed"); - return; + System.err.println("Method " + method + " has already been processed"); +// return; } if (!processed2.add(method.getQualifiedName())) { -// System.err.println("Method " + method + " has already been processed"); - return; + System.err.println("Method " + method + " has already been processed"); +// return; } if (method.isNative()) { System.err.println("native method " + method); -// return; +// return; } try { MethodSummary summary = methodSummaryProvider.getSummary(this, method); @@ -143,7 +143,7 @@ private void onMethodImplementationInvoked(AnalysisMethod method) { markMethodInvoked(invokedMethod); } for (AnalysisMethod invokedMethod : summary.implementationInvokedMethods) { - markMethodInvoked(invokedMethod); +// markMethodInvoked(invokedMethod); markMethodImplementationInvoked(invokedMethod, method); } for (AnalysisType type : summary.accessedTypes) { @@ -175,7 +175,7 @@ private void onMethodImplementationInvoked(AnalysisMethod method) { System.err.println("Parsing reason: " + method.getReason()); ex.printStackTrace(); } - if (method.getName().contains("VTable")) { + if (method.getName().contains("VTable") || method.getName().equals("getMutexes") || method.getName().equals("position")) { System.out.println("Successfully parsed " + method); } } @@ -231,16 +231,18 @@ private void onMethodInvoked(AnalysisMethod method) { @Override public boolean finish() throws InterruptedException { + universe.setAnalysisDataValid(false); for (int i = 0; i < 10; i++) { if (!executor.isStarted()) { executor.start(); } executor.complete(); executor.shutdown(); - executor.init(); + executor.init(timing); checkObjectGraph(); } + universe.setAnalysisDataValid(true); return true; // while (true) { // boolean quiescent = executorService.awaitQuiescence(100, TimeUnit.MILLISECONDS); diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java index a5b09f971ee7..72b46ed3ec24 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java @@ -66,7 +66,7 @@ public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { // System.out.println("1 Analyzed graph: " + method.getAnalyzedGraph()); if (method.isIntrinsicMethod()) { System.err.println("this is intrinsic: " + method); -// return MethodSummary.EMPTY; +// return MethodSummary.EMPTY; } AnalysisParsedGraph analysisParsedGraph = method.ensureGraphParsed(bb); if (analysisParsedGraph.getEncodedGraph() == null) { @@ -75,7 +75,7 @@ public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { } if (GuardedAnnotationAccess.isAnnotationPresent(method, Node.NodeIntrinsic.class)) { System.err.println("parsing an intrinsic: " + method); -// return MethodSummary.EMPTY; +// return MethodSummary.EMPTY; } // System.out.println("2 Analyzed graph: " + method.getAnalyzedGraph()); // System.out.println("analysis parsed graph " + analysisParsedGraph); @@ -89,6 +89,11 @@ public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { // to preserve the graphs for compilation method.setAnalyzedGraph(decoded); + ResolvedJavaMethod wrapped = method.wrapped; + while (wrapped instanceof AnalysisMethod) { + wrapped = ((AnalysisMethod) wrapped).wrapped; + } + AnalysisUniverse.graphs.put(wrapped, decoded); List accessedTypes = new ArrayList<>(); List instantiatedTypes = new ArrayList<>(); @@ -132,8 +137,9 @@ public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { Invoke node = (Invoke) n; CallTargetNode.InvokeKind kind = node.getInvokeKind(); AnalysisMethod targetMethod = analysisMethod(node.getTargetMethod()); - if (targetMethod == null) + if (targetMethod == null) { continue; + } if (kind.isDirect()) { implementationInvokedMethods.add(targetMethod); } else { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java index 0de4700a8bb5..d7e3c78fbf98 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java @@ -41,6 +41,7 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ForkJoinPool; +import com.oracle.graal.pointsto.meta.AnalysisUniverse; import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; @@ -409,7 +410,7 @@ public void finish(DebugContext debug) { * but are no longer reachable now. */ for (HostedMethod method : universe.getMethods()) { - method.wrapped.setAnalyzedGraph(null); +// method.wrapped.setAnalyzedGraph(null); } if (SubstrateOptions.AOTInline.getValue() && SubstrateOptions.AOTTrivialInline.getValue()) { @@ -788,6 +789,13 @@ protected void doParse(DebugContext debug, ParseTask task) { private StructuredGraph transplantGraph(DebugContext debug, HostedMethod hMethod, CompileReason reason) { AnalysisMethod aMethod = hMethod.getWrapped(); StructuredGraph aGraph = aMethod.getAnalyzedGraph(); + if (aGraph == null) { + ResolvedJavaMethod wrapped = aMethod.wrapped; + while (wrapped instanceof AnalysisMethod) { + wrapped = ((AnalysisMethod) wrapped).wrapped; + } + aGraph = AnalysisUniverse.graphs.get(wrapped); + } if (aGraph == null) { throw VMError.shouldNotReachHere("Method not parsed during static analysis: " + aMethod.format("%r %H.%n(%p)") + ". Reachable from: " + reason); } @@ -796,7 +804,7 @@ private StructuredGraph transplantGraph(DebugContext debug, HostedMethod hMethod * The graph in the analysis universe is no longer necessary once it is transplanted into * the hosted universe. */ - aMethod.setAnalyzedGraph(null); + // aMethod.setAnalyzedGraph(null); OptionValues options = getCustomizedOptions(debug); /* From 5d14085674bc9ad39f0fe8f935de6c55a7850a36 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Wed, 6 Oct 2021 16:50:33 +0200 Subject: [PATCH 10/65] implementation in progress --- .../graal/reachability/ReachabilityAnalysis.java | 15 ++++++++++++--- .../svm/hosted/phases/StrengthenStampsPhase.java | 8 ++++---- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index d93963bea462..eba7691096bd 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -68,7 +68,7 @@ public AnalysisType addRootClass(AnalysisType type, boolean addFields, boolean a } } - markTypeInstantiated(type); + markTypeReachable(type); if (type.getSuperclass() != null) { addRootClass(type.getSuperclass(), addFields, addArrayClass); @@ -111,6 +111,7 @@ public AnalysisMethod addRootMethod(AnalysisMethod method) { public void markMethodImplementationInvoked(AnalysisMethod method, Object reason) { if (method == null) { System.err.println("Null method received"); + System.out.println("reson: " + reason); new RuntimeException().printStackTrace(); return; } @@ -127,11 +128,11 @@ public void markMethodImplementationInvoked(AnalysisMethod method, Object reason private void onMethodImplementationInvoked(AnalysisMethod method) { if (!processed.add(method)) { System.err.println("Method " + method + " has already been processed"); -// return; +// return; } if (!processed2.add(method.getQualifiedName())) { System.err.println("Method " + method + " has already been processed"); -// return; +// return; } if (method.isNative()) { System.err.println("native method " + method); @@ -206,6 +207,10 @@ public void markTypeInstantiated(AnalysisType type) { Set invokedMethods = current.getInvokedMethods(); for (AnalysisMethod method : invokedMethods) { AnalysisMethod implementationInvokedMethod = type.resolveConcreteMethod(method, current); + if (implementationInvokedMethod == null) { + System.out.println("onMethodInvoked: method " + method + " on type " + current + " is null"); + continue; + } markMethodImplementationInvoked(implementationInvokedMethod, type); // todo better // reason } @@ -225,6 +230,10 @@ private void onMethodInvoked(AnalysisMethod method) { Set instantiatedSubtypes = clazz.getInstantiatedSubtypes(); for (AnalysisType subtype : instantiatedSubtypes) { AnalysisMethod resolvedMethod = subtype.resolveConcreteMethod(method, clazz); + if (resolvedMethod == null) { + System.out.println("onMethodInvoked: method " + method + " on type " + subtype + " is null"); + continue; + } markMethodImplementationInvoked(resolvedMethod, method); // todo better reason } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/StrengthenStampsPhase.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/StrengthenStampsPhase.java index 125ce536fdf0..a20a13eb947d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/StrengthenStampsPhase.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/StrengthenStampsPhase.java @@ -85,7 +85,7 @@ protected void run(StructuredGraph graph) { Stamp newStamp = strengthen(node.stamp(NodeView.DEFAULT)); if (newStamp != null) { - assert !parseOnce : "Must be done by StrengthenGraphs"; + // assert !parseOnce : "Must be done by StrengthenGraphs"; node.setStamp(newStamp); } } @@ -98,7 +98,7 @@ protected void run(StructuredGraph graph) { InstanceOfNode node = (InstanceOfNode) n; ObjectStamp newStamp = (ObjectStamp) strengthen(node.getCheckedStamp()); if (newStamp != null) { - assert !parseOnce : "Must be done by StrengthenGraphs"; + // assert !parseOnce : "Must be done by StrengthenGraphs"; node.replaceAndDelete(graph.addOrUniqueWithInputs(InstanceOfNode.createHelper(newStamp, node.getValue(), node.profile(), node.getAnchor()))); } @@ -106,7 +106,7 @@ protected void run(StructuredGraph graph) { PiNode node = (PiNode) n; Stamp newStamp = strengthen(node.piStamp()); if (newStamp != null) { - assert !parseOnce : "Must be done by StrengthenGraphs"; + // assert !parseOnce : "Must be done by StrengthenGraphs"; node.strengthenPiStamp(newStamp); } } @@ -166,7 +166,7 @@ private void updateStamp(ValueNode node, JavaTypeProfile typeProfile) { if (typeProfile != null) { Stamp newStamp = strengthenStamp(node, typeProfile); if (!newStamp.equals(node.stamp(NodeView.DEFAULT))) { - assert !parseOnce : "Must be done by StrengthenGraphs"; + // assert !parseOnce : "Must be done by StrengthenGraphs"; node.getDebug().log("STAMP UPDATE method %s node %s old %s new %s\n", node.graph().method().format("%H.%n(%p)"), node, node.stamp(NodeView.DEFAULT), newStamp); node.setStamp(newStamp); } From 584c2f4de517b8886e4068844e3eb2d119b8b7b9 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Thu, 7 Oct 2021 14:42:28 +0200 Subject: [PATCH 11/65] revert unnecessary changes in AnalysisParsedGraph --- .../pointsto/flow/AnalysisParsedGraph.java | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/AnalysisParsedGraph.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/AnalysisParsedGraph.java index dfa7ad642b56..8665d25fab08 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/AnalysisParsedGraph.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/AnalysisParsedGraph.java @@ -24,7 +24,6 @@ */ package com.oracle.graal.pointsto.flow; -import com.oracle.graal.pointsto.meta.HostedProviders; import org.graalvm.compiler.api.runtime.GraalJVMCICompiler; import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; @@ -39,7 +38,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.printer.GraalDebugHandlersFactory; @@ -103,21 +101,13 @@ public static AnalysisParsedGraph parseBytecode(BigBang bb, AnalysisMethod metho return optimizeAndEncode(bb, method, graph, false); } - HostedProviders providers = bb.getProviders(); - GraphBuilderConfiguration.Plugins graphBuilderPlugins = providers.getGraphBuilderPlugins(); - if (graphBuilderPlugins != null) { - InvocationPlugins invocationPlugins = graphBuilderPlugins.getInvocationPlugins(); - InvocationPlugin plugin = invocationPlugins.lookupInvocation(method); - if (plugin != null && !plugin.inlineOnly()) { - Bytecode code = new ResolvedJavaMethodBytecode(method); - graph = new SubstrateIntrinsicGraphBuilder(options, debug, bb.getProviders(), code).buildGraph(plugin); - if (graph != null) { - return optimizeAndEncode(bb, method, graph, true); - } + InvocationPlugin plugin = bb.getProviders().getGraphBuilderPlugins().getInvocationPlugins().lookupInvocation(method); + if (plugin != null && !plugin.inlineOnly()) { + Bytecode code = new ResolvedJavaMethodBytecode(method); + graph = new SubstrateIntrinsicGraphBuilder(options, debug, bb.getProviders(), code).buildGraph(plugin); + if (graph != null) { + return optimizeAndEncode(bb, method, graph, true); } - } else { - // todo what to do? - System.err.println("errr??"); } if (method.getCode() == null) { From efdc71c122ce5de886ebc4182a42ab67b7574628 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Thu, 7 Oct 2021 15:01:40 +0200 Subject: [PATCH 12/65] cleanup --- .../src/com/oracle/graal/pointsto/BigBang.java | 2 ++ .../src/com/oracle/graal/pointsto/PointsToAnalysis.java | 1 + .../src/com/oracle/graal/pointsto/meta/AnalysisType.java | 9 +-------- .../com/oracle/graal/pointsto/meta/AnalysisUniverse.java | 6 +----- .../graal/pointsto/phases/InlineBeforeAnalysis.java | 3 +-- .../oracle/graal/reachability/ReachabilityAnalysis.java | 1 - .../hosted/analysis/NativeImageReachabilityAnalysis.java | 8 ++++++++ 7 files changed, 14 insertions(+), 16 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java index c278ad7368e1..8d40f8598968 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java @@ -104,6 +104,8 @@ public interface BigBang extends ReachabilityAnalysis, HeapScanning { void runAnalysis(DebugContext debug, Function duringAnalysisAction) throws InterruptedException; + boolean strengthenGraalGraphs(); + Replacements getReplacements(); /** You can blacklist certain callees here. */ diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java index 59763731c772..55799795c230 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java @@ -207,6 +207,7 @@ public void printTimerStatistics(PrintWriter out) { StatisticsPrinter.printLast(out, "total_memory_bytes", analysisTimer.getTotalMemory()); } + @Override public boolean strengthenGraalGraphs() { return strengthenGraalGraphs; } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java index 20774d6fe430..30d977a9b0a8 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java @@ -880,14 +880,7 @@ public AnalysisMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType public AnalysisMethod resolveConcreteMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) { Object resolvedMethod = resolvedMethods.get(method); if (resolvedMethod == null) { - ResolvedJavaMethod current = method; - while (current instanceof AnalysisMethod) { - current = ((AnalysisMethod) current).wrapped; - } - ResolvedJavaMethod substMethod = universe.substitutions.resolve(current); - while (substMethod instanceof AnalysisMethod) { - substMethod = ((AnalysisMethod) substMethod).wrapped; - } + ResolvedJavaMethod substMethod = universe.substitutions.resolve(((AnalysisMethod) method).wrapped); /* * We do not want any access checks to be performed, so we use the method's declaring * class as the caller type. diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java index d51839e8819d..961bdde4f01d 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java @@ -38,10 +38,8 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; -import com.oracle.graal.pointsto.flow.AnalysisParsedGraph; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.SuppressFBWarnings; -import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.word.WordBase; import com.oracle.graal.pointsto.AnalysisPolicy; @@ -90,8 +88,6 @@ public class AnalysisUniverse implements Universe { private final ConcurrentHashMap embeddedRoots = new ConcurrentHashMap<>(ESTIMATED_EMBEDDED_ROOTS); private final ConcurrentMap unsafeAccessedStaticFields = new ConcurrentHashMap<>(); - public static final ConcurrentMap graphs = new ConcurrentHashMap<>(); - private boolean sealed; private volatile AnalysisType[] typesById = new AnalysisType[ESTIMATED_NUMBER_OF_TYPES]; @@ -352,7 +348,7 @@ public JavaKind getStorageKind(ResolvedJavaType type, MetaAccessProvider metaAcc @Override public AnalysisField lookup(JavaField field) { if (field instanceof AnalysisField) { - System.err.println("Querying already made analysis type: " + field); + System.err.println("Querying already made analysis field: " + field); return ((AnalysisField) field); } JavaField result = lookupAllowUnresolved(field); diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysis.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysis.java index 4da18e1fb81e..b7d60e8566a4 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysis.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysis.java @@ -53,7 +53,6 @@ import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import org.graalvm.compiler.replacements.PEGraphDecoder; -import com.oracle.graal.pointsto.PointsToAnalysis; import com.oracle.graal.pointsto.flow.AnalysisParsedGraph; import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.svm.util.ClassUtil; @@ -95,7 +94,7 @@ public static StructuredGraph decodeGraph(BigBang bb, AnalysisMethod method, Ana try (DebugContext.Scope s = debug.scope("InlineBeforeAnalysis", result)) { - if (((bb instanceof PointsToAnalysis) && ((PointsToAnalysis) bb).strengthenGraalGraphs()) && Options.InlineBeforeAnalysis.getValue(bb.getOptions())) { + if (bb.strengthenGraalGraphs() && Options.InlineBeforeAnalysis.getValue(bb.getOptions())) { InlineBeforeAnalysisGraphDecoder decoder = new InlineBeforeAnalysisGraphDecoder<>(bb, bb.getHostVM().inlineBeforeAnalysisPolicy(), result); decoder.decode(method, false, result.trackNodeSourcePosition()); } else { diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index eba7691096bd..900f28c14b04 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -118,7 +118,6 @@ public void markMethodImplementationInvoked(AnalysisMethod method, Object reason if (!method.registerAsImplementationInvoked(null)) { return; } - method.setReason(reason); schedule(() -> onMethodImplementationInvoked(method)); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java index ec3ad0608029..d26c83722a57 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java @@ -28,6 +28,7 @@ import com.oracle.graal.pointsto.meta.HostedProviders; import com.oracle.graal.reachability.MethodSummaryProvider; import com.oracle.graal.reachability.ReachabilityAnalysis; +import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.graal.meta.SubstrateReplacements; import com.oracle.svm.hosted.SVMHost; import com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor; @@ -38,12 +39,19 @@ public class NativeImageReachabilityAnalysis extends ReachabilityAnalysis implements Inflation { private final AnnotationSubstitutionProcessor annotationSubstitutionProcessor; + private final boolean strengthenGraalGraphs; public NativeImageReachabilityAnalysis(OptionValues options, AnalysisUniverse universe, HostedProviders providers, AnnotationSubstitutionProcessor annotationSubstitutionProcessor, ForkJoinPool executor, Runnable heartbeatCallback, MethodSummaryProvider methodSummaryProvider) { super(options, universe, providers, universe.hostVM(), executor, heartbeatCallback, new SubstrateUnsupportedFeatures(), methodSummaryProvider); this.annotationSubstitutionProcessor = annotationSubstitutionProcessor; + this.strengthenGraalGraphs = SubstrateOptions.parseOnce(); + } + + @Override + public boolean strengthenGraalGraphs() { + return strengthenGraalGraphs; } @Override From 6efa42db52b1af319008f65b44262a30152e1523 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Thu, 7 Oct 2021 15:21:49 +0200 Subject: [PATCH 13/65] more cleanup --- .../pointsto/AbstractAnalysisEngine.java | 1 - .../graal/pointsto/PointsToAnalysis.java | 9 +------ .../pointsto/results/DummyResultsBuilder.java | 25 ++++++++++++++++++- .../reachability/ReachabilityAnalysis.java | 10 -------- .../SimpleInMemoryMethodSummaryProvider.java | 5 ---- .../oracle/svm/hosted/code/CompileQueue.java | 8 ------ 6 files changed, 25 insertions(+), 33 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java index 8e284355e3fe..8ee601d49ff9 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java @@ -204,7 +204,6 @@ public HostVM getHostVM() { protected void schedule(Runnable task) { executor.execute((d) -> task.run()); - // executorService.submit(task); } @Override diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java index 55799795c230..8d85ee427f7e 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java @@ -763,14 +763,7 @@ private boolean analysisModified() throws InterruptedException { @SuppressFBWarnings(value = "NP_NONNULL_PARAM_VIOLATION", justification = "ForkJoinPool does support null for the exception handler.") public static ForkJoinPool createExecutor(DebugContext debug, int numberOfThreads) { ForkJoinPool.ForkJoinWorkerThreadFactory factory = debugThreadFactory(debug.areScopesEnabled() || debug.areMetricsEnabled() ? debug : null); - return new ForkJoinPool(numberOfThreads, factory, new Thread.UncaughtExceptionHandler() { - @Override - public void uncaughtException(Thread t, Throwable e) { - System.err.println("Thread " + t); - e.printStackTrace(); - System.err.println("---"); - } - }, false); + return new ForkJoinPool(numberOfThreads, factory, null, false); } private static ForkJoinPool.ForkJoinWorkerThreadFactory debugThreadFactory(DebugContext debug) { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/DummyResultsBuilder.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/DummyResultsBuilder.java index 91f0d8c48daa..e6050e899b02 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/DummyResultsBuilder.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/DummyResultsBuilder.java @@ -1,7 +1,30 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ package com.oracle.graal.pointsto.results; import com.oracle.graal.pointsto.BigBang; -import com.oracle.graal.pointsto.PointsToAnalysis; import com.oracle.graal.pointsto.infrastructure.Universe; import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisMethod; diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index 900f28c14b04..2159569a66fe 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -175,9 +175,6 @@ private void onMethodImplementationInvoked(AnalysisMethod method) { System.err.println("Parsing reason: " + method.getReason()); ex.printStackTrace(); } - if (method.getName().contains("VTable") || method.getName().equals("getMutexes") || method.getName().equals("position")) { - System.out.println("Successfully parsed " + method); - } } @Override @@ -252,13 +249,6 @@ public boolean finish() throws InterruptedException { } universe.setAnalysisDataValid(true); return true; -// while (true) { -// boolean quiescent = executorService.awaitQuiescence(100, TimeUnit.MILLISECONDS); -// if (quiescent) { -// break; -// } -// } -// return false; } private ObjectScanner.ReusableSet scannedObjects = new ObjectScanner.ReusableSet(); diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java index 72b46ed3ec24..9a27a993184b 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java @@ -89,11 +89,6 @@ public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { // to preserve the graphs for compilation method.setAnalyzedGraph(decoded); - ResolvedJavaMethod wrapped = method.wrapped; - while (wrapped instanceof AnalysisMethod) { - wrapped = ((AnalysisMethod) wrapped).wrapped; - } - AnalysisUniverse.graphs.put(wrapped, decoded); List accessedTypes = new ArrayList<>(); List instantiatedTypes = new ArrayList<>(); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java index d7e3c78fbf98..bd591129a554 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java @@ -41,7 +41,6 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ForkJoinPool; -import com.oracle.graal.pointsto.meta.AnalysisUniverse; import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; @@ -789,13 +788,6 @@ protected void doParse(DebugContext debug, ParseTask task) { private StructuredGraph transplantGraph(DebugContext debug, HostedMethod hMethod, CompileReason reason) { AnalysisMethod aMethod = hMethod.getWrapped(); StructuredGraph aGraph = aMethod.getAnalyzedGraph(); - if (aGraph == null) { - ResolvedJavaMethod wrapped = aMethod.wrapped; - while (wrapped instanceof AnalysisMethod) { - wrapped = ((AnalysisMethod) wrapped).wrapped; - } - aGraph = AnalysisUniverse.graphs.get(wrapped); - } if (aGraph == null) { throw VMError.shouldNotReachHere("Method not parsed during static analysis: " + aMethod.format("%r %H.%n(%p)") + ". Reachable from: " + reason); } From 1bd030cf14c06620df0d93f70be8886e067e63a1 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Fri, 8 Oct 2021 10:33:38 +0200 Subject: [PATCH 14/65] more cleanup --- .../graal/reachability/ReachabilityAnalysis.java | 1 + .../SimpleInMemoryMethodSummaryProvider.java | 14 +++----------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index 2159569a66fe..d624fb9587d9 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -237,6 +237,7 @@ private void onMethodInvoked(AnalysisMethod method) { @Override public boolean finish() throws InterruptedException { universe.setAnalysisDataValid(false); + // todo transform into a real 'run until fixpoint' loop for (int i = 0; i < 10; i++) { if (!executor.isStarted()) { executor.start(); diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java index 9a27a993184b..9bc0d54a401f 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java @@ -61,9 +61,6 @@ public SimpleInMemoryMethodSummaryProvider(AnalysisUniverse universe) { @Override public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { - // todo clean this up -// System.out.println("Making a summary for " + method.format("%H.%n(%p)")); -// System.out.println("1 Analyzed graph: " + method.getAnalyzedGraph()); if (method.isIntrinsicMethod()) { System.err.println("this is intrinsic: " + method); // return MethodSummary.EMPTY; @@ -77,12 +74,9 @@ public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { System.err.println("parsing an intrinsic: " + method); // return MethodSummary.EMPTY; } -// System.out.println("2 Analyzed graph: " + method.getAnalyzedGraph()); -// System.out.println("analysis parsed graph " + analysisParsedGraph); -// System.out.println("Encoded graph " + analysisParsedGraph.getEncodedGraph()); + StructuredGraph decoded = InlineBeforeAnalysis.decodeGraph(bb, method, analysisParsedGraph); -// StructuredGraph decoded = analysisParsedGraph.graph; -// System.out.println("decoded " + decoded); + if (decoded == null) { throw AnalysisError.shouldNotReachHere("Failed to decode a graph for " + method.format("%H.%n(%p)")); } @@ -142,11 +136,9 @@ public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { } } } - MethodSummary summary = new MethodSummary(invokedMethods.toArray(new AnalysisMethod[0]), implementationInvokedMethods.toArray(new AnalysisMethod[0]), + return new MethodSummary(invokedMethods.toArray(new AnalysisMethod[0]), implementationInvokedMethods.toArray(new AnalysisMethod[0]), accessedTypes.toArray(new AnalysisType[0]), instantiatedTypes.toArray(new AnalysisType[0]), accessedFields.toArray(new AnalysisField[0]), embeddedConstants.toArray(new JavaConstant[0])); -// System.out.println("Made a summary " + summary); - return summary; } private AnalysisType analysisType(ResolvedJavaType type) { From fb14e111910e76a491b46736eae94c5454083e02 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Mon, 11 Oct 2021 11:56:58 +0200 Subject: [PATCH 15/65] differentiate between marking fields as read or written --- .../graal/pointsto/ReachabilityAnalysis.java | 4 ++++ .../graal/reachability/MethodSummary.java | 17 +++++++++++------ .../reachability/ReachabilityAnalysis.java | 17 +++++++++++++++-- .../SimpleInMemoryMethodSummaryProvider.java | 19 +++++++++++++++---- 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ReachabilityAnalysis.java index 5aa867756c2e..8bec56be5701 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ReachabilityAnalysis.java @@ -109,6 +109,10 @@ default void markFieldRead(AnalysisField field) { markFieldAccessed(field); } + default void markFieldWritten(AnalysisField field) { + markFieldAccessed(field); + } + void markMethodImplementationInvoked(AnalysisMethod method, Object reason); /** diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java index bb0cce821f42..e9b2a5cbe416 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java @@ -32,22 +32,26 @@ import java.util.Arrays; public class MethodSummary { - public static final MethodSummary EMPTY = new MethodSummary(new AnalysisMethod[0], new AnalysisMethod[0], new AnalysisType[0], new AnalysisType[0], new AnalysisField[0], new JavaConstant[0]); + public static final MethodSummary EMPTY = new MethodSummary(new AnalysisMethod[0], new AnalysisMethod[0], new AnalysisType[0], new AnalysisType[0], new AnalysisField[0], new AnalysisField[0], + new JavaConstant[0]); public final AnalysisMethod[] invokedMethods; public final AnalysisMethod[] implementationInvokedMethods; public final AnalysisType[] accessedTypes; public final AnalysisType[] instantiatedTypes; - public final AnalysisField[] accessedFields; + public final AnalysisField[] readFields; + public final AnalysisField[] writtenFields; public final JavaConstant[] embeddedConstants; - public MethodSummary(AnalysisMethod[] invokedMethods, AnalysisMethod[] implementationInvokedMethods, AnalysisType[] accessedTypes, AnalysisType[] instantiatedTypes, AnalysisField[] accessedFields, + public MethodSummary(AnalysisMethod[] invokedMethods, AnalysisMethod[] implementationInvokedMethods, AnalysisType[] accessedTypes, AnalysisType[] instantiatedTypes, AnalysisField[] readFields, + AnalysisField[] writtenFields, JavaConstant[] embeddedConstants) { this.invokedMethods = invokedMethods; this.implementationInvokedMethods = implementationInvokedMethods; this.accessedTypes = accessedTypes; this.instantiatedTypes = instantiatedTypes; - this.accessedFields = accessedFields; + this.readFields = readFields; + this.writtenFields = writtenFields; this.embeddedConstants = embeddedConstants; } @@ -55,10 +59,11 @@ public MethodSummary(AnalysisMethod[] invokedMethods, AnalysisMethod[] implement public String toString() { return "MethodSummary{" + "invokedMethods=" + Arrays.toString(invokedMethods) + - "implementationInvokedMethods=" + Arrays.toString(implementationInvokedMethods) + + ", implementationInvokedMethods=" + Arrays.toString(implementationInvokedMethods) + ", accessedTypes=" + Arrays.toString(accessedTypes) + ", instantiatedTypes=" + Arrays.toString(instantiatedTypes) + - ", accessedFields=" + Arrays.toString(accessedFields) + + ", readFields=" + Arrays.toString(readFields) + + ", writtenFields=" + Arrays.toString(writtenFields) + ", embeddedConstants=" + Arrays.toString(embeddedConstants) + '}'; } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index d624fb9587d9..176262aec36d 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -152,8 +152,11 @@ private void onMethodImplementationInvoked(AnalysisMethod method) { for (AnalysisType type : summary.instantiatedTypes) { markTypeInstantiated(type); } - for (AnalysisField field : summary.accessedFields) { - markFieldAccessed(field); + for (AnalysisField field : summary.readFields) { + markFieldRead(field); + } + for (AnalysisField field : summary.writtenFields) { + markFieldWritten(field); } for (JavaConstant constant : summary.embeddedConstants) { if (constant.getJavaKind() == JavaKind.Object && constant.isNonNull()) { @@ -182,6 +185,16 @@ public void markFieldAccessed(AnalysisField field) { field.registerAsAccessed(); } + @Override + public void markFieldRead(AnalysisField field) { + field.registerAsRead(null); + } + + @Override + public void markFieldWritten(AnalysisField field) { + field.registerAsWritten(null); + } + @Override public void markTypeReachable(AnalysisType type) { // todo double check whether all necessary logic is in diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java index 9bc0d54a401f..1d6267044fda 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java @@ -43,9 +43,11 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.java.AccessFieldNode; import org.graalvm.compiler.nodes.java.InstanceOfNode; +import org.graalvm.compiler.nodes.java.LoadFieldNode; import org.graalvm.compiler.nodes.java.NewArrayNode; import org.graalvm.compiler.nodes.java.NewInstanceNode; import org.graalvm.compiler.nodes.java.NewMultiArrayNode; +import org.graalvm.compiler.nodes.java.StoreFieldNode; import org.graalvm.util.GuardedAnnotationAccess; import java.util.ArrayList; @@ -86,7 +88,8 @@ public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { List accessedTypes = new ArrayList<>(); List instantiatedTypes = new ArrayList<>(); - List accessedFields = new ArrayList<>(); + List readFields = new ArrayList<>(); + List writtenFields = new ArrayList<>(); List invokedMethods = new ArrayList<>(); List implementationInvokedMethods = new ArrayList<>(); List embeddedConstants = new ArrayList<>(); @@ -120,8 +123,15 @@ public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { InstanceOfNode node = (InstanceOfNode) n; accessedTypes.add(analysisType(node.type().getType())); } else if (n instanceof AccessFieldNode) { - AccessFieldNode node = (AccessFieldNode) n; - accessedFields.add(analysisField(node.field())); + if (n instanceof LoadFieldNode) { + LoadFieldNode node = (LoadFieldNode) n; + readFields.add(analysisField(node.field())); + } else if (n instanceof StoreFieldNode) { + StoreFieldNode node = (StoreFieldNode) n; + writtenFields.add(analysisField(node.field())); + } else { + throw AnalysisError.shouldNotReachHere("Unhalded AccessFieldNode Type"); + } } else if (n instanceof Invoke) { Invoke node = (Invoke) n; CallTargetNode.InvokeKind kind = node.getInvokeKind(); @@ -138,7 +148,8 @@ public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { } return new MethodSummary(invokedMethods.toArray(new AnalysisMethod[0]), implementationInvokedMethods.toArray(new AnalysisMethod[0]), accessedTypes.toArray(new AnalysisType[0]), - instantiatedTypes.toArray(new AnalysisType[0]), accessedFields.toArray(new AnalysisField[0]), embeddedConstants.toArray(new JavaConstant[0])); + instantiatedTypes.toArray(new AnalysisType[0]), readFields.toArray(new AnalysisField[0]), writtenFields.toArray(new AnalysisField[0]), + embeddedConstants.toArray(new JavaConstant[0])); } private AnalysisType analysisType(ResolvedJavaType type) { From 050122d68b227a724b775bd14267eac6321cd71c Mon Sep 17 00:00:00 2001 From: David Kozak Date: Mon, 11 Oct 2021 12:29:14 +0200 Subject: [PATCH 16/65] add functionality from NativeImagePointsToAnalysis into NativeImageReachabilityAnalysis, teporarily as a copy until a proper abstraction in made --- .../reachability/ReachabilityAnalysis.java | 4 +- .../NativeImageReachabilityAnalysis.java | 546 ++++++++++++++++++ 2 files changed, 549 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index 176262aec36d..f508fda25a03 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -273,7 +273,7 @@ private void checkObjectGraph() throws InterruptedException { // scan constants boolean isParallel = PointstoOptions.ScanObjectsParallel.getValue(options); ObjectScanner objectScanner = new ReachabilityObjectScanner(this, isParallel ? executor : null, scannedObjects, metaAccess); -// checkObjectGraph(objectScanner); + checkObjectGraph(objectScanner); if (isParallel) { executor.start(); objectScanner.scanBootImageHeapRoots(null, null); @@ -285,6 +285,8 @@ private void checkObjectGraph() throws InterruptedException { } } + protected abstract void checkObjectGraph(ObjectScanner objectScanner); + @Override public void cleanupAfterAnalysis() { super.cleanupAfterAnalysis(); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java index d26c83722a57..4dd41301c608 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java @@ -24,20 +24,61 @@ */ package com.oracle.svm.hosted.analysis; +import com.oracle.graal.pointsto.ObjectScanner; +import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException; +import com.oracle.graal.pointsto.meta.AnalysisField; +import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; +import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.graal.pointsto.meta.HostedProviders; +import com.oracle.graal.pointsto.util.AnalysisError; import com.oracle.graal.reachability.MethodSummaryProvider; import com.oracle.graal.reachability.ReachabilityAnalysis; import com.oracle.svm.core.SubstrateOptions; +import com.oracle.svm.core.annotate.UnknownObjectField; +import com.oracle.svm.core.annotate.UnknownPrimitiveField; import com.oracle.svm.core.graal.meta.SubstrateReplacements; +import com.oracle.svm.core.hub.AnnotatedSuperInfo; +import com.oracle.svm.core.hub.AnnotationsEncoding; +import com.oracle.svm.core.hub.DynamicHub; +import com.oracle.svm.core.hub.GenericInfo; +import com.oracle.svm.core.meta.SubstrateObjectConstant; import com.oracle.svm.hosted.SVMHost; +import com.oracle.svm.hosted.meta.HostedType; import com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaType; import org.graalvm.compiler.options.OptionValues; +import org.graalvm.word.WordBase; +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedType; +import java.lang.reflect.MalformedParameterizedTypeException; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ForkJoinPool; +import java.util.stream.Collectors; + +import static jdk.vm.ci.common.JVMCIError.shouldNotReachHere; public class NativeImageReachabilityAnalysis extends ReachabilityAnalysis implements Inflation { + private Set handledUnknownValueFields = ConcurrentHashMap.newKeySet(); + private Map genericInterfacesMap = new ConcurrentHashMap<>(); + private Map annotatedInterfacesMap = new ConcurrentHashMap<>();; + private Map interfacesEncodings = new ConcurrentHashMap<>();; + private final AnnotationSubstitutionProcessor annotationSubstitutionProcessor; private final boolean strengthenGraalGraphs; @@ -59,6 +100,25 @@ public AnnotationSubstitutionProcessor getAnnotationSubstitutionProcessor() { return annotationSubstitutionProcessor; } + @Override + protected void checkObjectGraph(ObjectScanner objectScanner) { + // todo refactor into a common class instead of this ugly copy + universe.getFields().forEach(this::handleUnknownValueField); + universe.getTypes().stream().filter(AnalysisType::isReachable).forEach(this::checkType); + + /* Scan hubs of all types that end up in the native image. */ + universe.getTypes().stream().filter(AnalysisType::isReachable).forEach(type -> scanHub(objectScanner, type)); + } + + @Override + public void cleanupAfterAnalysis() { + super.cleanupAfterAnalysis(); + handledUnknownValueFields = null; + genericInterfacesMap = null; + annotatedInterfacesMap = null; + interfacesEncodings = null; + } + @Override public SubstrateReplacements getReplacements() { return (SubstrateReplacements) super.getReplacements(); @@ -73,4 +133,490 @@ public SVMHost getHostVM() { public void checkUserLimitations() { // todo } + + public void checkType(AnalysisType type) { + assert type.isReachable(); + DynamicHub hub = getHostVM().dynamicHub(type); + if (hub.getGenericInfo() == null) { + fillGenericInfo(type, hub); + } + if (hub.getAnnotatedSuperInfo() == null) { + fillAnnotatedSuperInfo(type, hub); + } + + if (type.getJavaKind() == JavaKind.Object) { + if (type.isArray()) { + hub.getComponentHub().setArrayHub(hub); + } + + try { + AnalysisType enclosingType = type.getEnclosingType(); + if (enclosingType != null) { + hub.setEnclosingClass(getHostVM().dynamicHub(enclosingType)); + } + } catch (UnsupportedFeatureException ex) { + getUnsupportedFeatures().addMessage(type.toJavaName(true), null, ex.getMessage(), null, ex); + } + + if (hub.getInterfacesEncoding() == null) { + fillInterfaces(type, hub); + } + + /* + * Support for Java annotations. + */ + try { + /* + * Get the annotations from the wrapped type since AnalysisType.getAnnotations() + * defends against JDK-7183985 and we want to get the original behavior. + */ + Annotation[] annotations = type.getWrappedWithoutResolve().getAnnotations(); + Annotation[] declared = type.getWrappedWithoutResolve().getDeclaredAnnotations(); + hub.setAnnotationsEncoding(encodeAnnotations(metaAccess, annotations, declared, hub.getAnnotationsEncoding())); + } catch (ArrayStoreException e) { + /* If we hit JDK-7183985 just encode the exception. */ + hub.setAnnotationsEncoding(e); + } + + /* + * Support for Java enumerations. + */ + if (type.isEnum() && hub.shouldInitEnumConstants()) { + if (getHostVM().getClassInitializationSupport().shouldInitializeAtRuntime(type)) { + hub.initEnumConstantsAtRuntime(type.getJavaClass()); + } else { + /* + * We want to retrieve the enum constant array that is maintained as a private + * static field in the enumeration class. We do not want a copy because that + * would mean we have the array twice in the native image: as the static field, + * and in the enumConstant field of DynamicHub. The only way to get the original + * value is via a reflective field access, and we even have to guess the field + * name. + */ + AnalysisField found = null; + for (AnalysisField f : type.getStaticFields()) { + if (f.getName().endsWith("$VALUES")) { + if (found != null) { + /* + * Enumeration has more than one static field with enumeration + * values. Bailout and use Class.getEnumConstants() to get the value + * instead. + */ + found = null; + break; + } + found = f; + } + } + Enum[] enumConstants; + if (found == null) { + /* + * We could not find a unique $VALUES field, so we use the value returned by + * Class.getEnumConstants(). This is not ideal since + * Class.getEnumConstants() returns a copy of the array, so we will have two + * arrays with the same content in the image heap, but it is better than + * failing image generation. + */ + enumConstants = (Enum[]) type.getJavaClass().getEnumConstants(); + } else { + enumConstants = (Enum[]) SubstrateObjectConstant.asObject(getConstantReflectionProvider().readFieldValue(found, null)); + assert enumConstants != null; + } + hub.initEnumConstants(enumConstants); + } + } + } + } + + static class GenericInterfacesEncodingKey { + final Type[] interfaces; + + GenericInterfacesEncodingKey(Type[] aInterfaces) { + this.interfaces = aInterfaces; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof NativeImagePointsToAnalysis.GenericInterfacesEncodingKey && Arrays.equals(interfaces, ((NativeImagePointsToAnalysis.GenericInterfacesEncodingKey) obj).interfaces); + } + + @Override + public int hashCode() { + return Arrays.hashCode(interfaces); + } + } + + /** Modified copy of {@link Arrays#equals(Object[], Object[])}. */ + private static boolean shallowEquals(Object[] a, Object[] a2) { + if (a == a2) { + return true; + } else if (a == null || a2 == null) { + return false; + } + int length = a.length; + if (a2.length != length) { + return false; + } + for (int i = 0; i < length; i++) { + /* Modification: use reference equality. */ + if (a[i] != a2[i]) { + return false; + } + } + return true; + } + + /** Modified copy of {@link Arrays#hashCode(Object[])}. */ + private static int shallowHashCode(Object[] a) { + if (a == null) { + return 0; + } + int result = 1; + + for (Object element : a) { + /* Modification: use identity hash code. */ + result = 31 * result + System.identityHashCode(element); + } + return result; + } + + static class AnnotatedInterfacesEncodingKey { + final AnnotatedType[] interfaces; + + AnnotatedInterfacesEncodingKey(AnnotatedType[] aInterfaces) { + this.interfaces = aInterfaces; + } + + /* + * JDK 12 introduced a broken implementation of hashCode() and equals() for the + * implementation classes of annotated types, leading to an infinite recursion. Tracked as + * JDK-8224012. As a workaround, we use shallow implementations that only depend on the + * identity hash code and reference equality. This is the same behavior as on JDK 8 and JDK + * 11 anyway. + */ + + @Override + public boolean equals(Object obj) { + return obj instanceof NativeImagePointsToAnalysis.AnnotatedInterfacesEncodingKey && + shallowEquals(interfaces, ((NativeImagePointsToAnalysis.AnnotatedInterfacesEncodingKey) obj).interfaces); + } + + @Override + public int hashCode() { + return shallowHashCode(interfaces); + } + } + + private void fillGenericInfo(AnalysisType type, DynamicHub hub) { + Class javaClass = type.getJavaClass(); + + TypeVariable[] typeParameters = javaClass.getTypeParameters(); + + Type[] allGenericInterfaces; + try { + allGenericInterfaces = javaClass.getGenericInterfaces(); + } catch (MalformedParameterizedTypeException | TypeNotPresentException | LinkageError t) { + /* + * Loading generic interfaces can fail due to missing types. Ignore the exception and + * return an empty array. + */ + allGenericInterfaces = new Type[0]; + } + + Type[] genericInterfaces = Arrays.stream(allGenericInterfaces).filter(this::isTypeAllowed).toArray(Type[]::new); + Type[] cachedGenericInterfaces; + try { + cachedGenericInterfaces = genericInterfacesMap.computeIfAbsent(new NativeImageReachabilityAnalysis.GenericInterfacesEncodingKey(genericInterfaces), k -> genericInterfaces); + } catch (MalformedParameterizedTypeException | TypeNotPresentException | LinkageError t) { + /* + * Computing the hash code of generic interfaces can fail due to missing types. Ignore + * the exception and proceed without caching. De-duplication of generic interfaces is an + * optimization and not necessary for correctness. + */ + cachedGenericInterfaces = genericInterfaces; + } + + Type genericSuperClass; + try { + genericSuperClass = javaClass.getGenericSuperclass(); + } catch (MalformedParameterizedTypeException | TypeNotPresentException | LinkageError t) { + /* + * Loading the generic super class can fail due to missing types. Ignore the exception + * and return null. + */ + genericSuperClass = null; + } + if (!isTypeAllowed(genericSuperClass)) { + genericSuperClass = null; + } + hub.setGenericInfo(GenericInfo.factory(typeParameters, cachedGenericInterfaces, genericSuperClass)); + } + + private void fillAnnotatedSuperInfo(AnalysisType type, DynamicHub hub) { + Class javaClass = type.getJavaClass(); + + AnnotatedType annotatedSuperclass; + try { + annotatedSuperclass = javaClass.getAnnotatedSuperclass(); + } catch (MalformedParameterizedTypeException | TypeNotPresentException | LinkageError t) { + /* + * Loading the annotated super class can fail due to missing types. Ignore the exception + * and return null. + */ + annotatedSuperclass = null; + } + if (annotatedSuperclass != null && !isTypeAllowed(annotatedSuperclass.getType())) { + annotatedSuperclass = null; + } + + AnnotatedType[] allAnnotatedInterfaces; + try { + allAnnotatedInterfaces = javaClass.getAnnotatedInterfaces(); + } catch (MalformedParameterizedTypeException | TypeNotPresentException | LinkageError t) { + /* + * Loading annotated interfaces can fail due to missing types. Ignore the exception and + * return an empty array. + */ + allAnnotatedInterfaces = new AnnotatedType[0]; + } + + AnnotatedType[] annotatedInterfaces = Arrays.stream(allAnnotatedInterfaces) + .filter(ai -> isTypeAllowed(ai.getType())).toArray(AnnotatedType[]::new); + AnnotatedType[] cachedAnnotatedInterfaces = annotatedInterfacesMap.computeIfAbsent( + new NativeImageReachabilityAnalysis.AnnotatedInterfacesEncodingKey(annotatedInterfaces), k -> annotatedInterfaces); + hub.setAnnotatedSuperInfo(AnnotatedSuperInfo.factory(annotatedSuperclass, cachedAnnotatedInterfaces)); + } + + private boolean isTypeAllowed(Type t) { + if (t instanceof Class) { + Optional resolved = metaAccess.optionalLookupJavaType((Class) t); + return resolved.isPresent() && hostVM.platformSupported(universe, resolved.get()); + } + return true; + } + + class InterfacesEncodingKey { + final AnalysisType[] aInterfaces; + + InterfacesEncodingKey(AnalysisType[] aInterfaces) { + this.aInterfaces = aInterfaces; + } + + DynamicHub[] createHubs() { + SVMHost svmHost = (SVMHost) hostVM; + DynamicHub[] hubs = new DynamicHub[aInterfaces.length]; + for (int i = 0; i < hubs.length; i++) { + hubs[i] = svmHost.dynamicHub(aInterfaces[i]); + } + return hubs; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof NativeImageReachabilityAnalysis.InterfacesEncodingKey && Arrays.equals(aInterfaces, ((NativeImageReachabilityAnalysis.InterfacesEncodingKey) obj).aInterfaces); + } + + @Override + public int hashCode() { + return Arrays.hashCode(aInterfaces); + } + } + + /** + * Fill array returned by Class.getInterfaces(). + */ + private void fillInterfaces(AnalysisType type, DynamicHub hub) { + SVMHost svmHost = (SVMHost) hostVM; + + AnalysisType[] aInterfaces = type.getInterfaces(); + if (aInterfaces.length == 0) { + hub.setInterfacesEncoding(null); + } else if (aInterfaces.length == 1) { + hub.setInterfacesEncoding(svmHost.dynamicHub(aInterfaces[0])); + } else { + /* + * Many interfaces arrays are the same, e.g., all arrays implement the same two + * interfaces. We want to avoid duplicate arrays with the same content in the native + * image heap. + */ + hub.setInterfacesEncoding( + interfacesEncodings.computeIfAbsent(new NativeImageReachabilityAnalysis.InterfacesEncodingKey(aInterfaces), InterfacesEncodingKey::createHubs)); + } + } + + private void scanHub(ObjectScanner objectScanner, AnalysisType type) { + SVMHost svmHost = (SVMHost) hostVM; + JavaConstant hubConstant = SubstrateObjectConstant.forObject(svmHost.dynamicHub(type)); + objectScanner.scanConstant(hubConstant, ObjectScanner.ScanReason.HUB); + } + + private void handleUnknownValueField(AnalysisField field) { + if (handledUnknownValueFields.contains(field)) { + return; + } + if (!field.isAccessed()) { + /* + * Field is not reachable yet, so do no process it. In particular, we must not register + * types listed in the @UnknownObjectField annotation as allocated when the field is not + * yet reachable + */ + return; + } + + UnknownObjectField unknownObjectField = field.getAnnotation(UnknownObjectField.class); + UnknownPrimitiveField unknownPrimitiveField = field.getAnnotation(UnknownPrimitiveField.class); + if (unknownObjectField != null) { + assert !Modifier.isFinal(field.getModifiers()) : "@UnknownObjectField annotated field " + field.format("%H.%n") + " cannot be final"; + assert field.getJavaKind() == JavaKind.Object; + + field.setCanBeNull(unknownObjectField.canBeNull()); + + List aAnnotationTypes = extractAnnotationTypes(field, unknownObjectField); + + for (AnalysisType type : aAnnotationTypes) { + type.registerAsAllocated(null); + } + + /* + * Use the annotation types, instead of the declared type, in the UnknownObjectField + * annotated fields initialization. + */ + handleUnknownObjectField(field, aAnnotationTypes.toArray(new AnalysisType[0])); + + } else if (unknownPrimitiveField != null) { + assert !Modifier.isFinal(field.getModifiers()) : "@UnknownPrimitiveField annotated field " + field.format("%H.%n") + " cannot be final"; + /* + * Register a primitive field as containing unknown values(s), i.e., is usually written + * only in hosted code. + */ + + field.registerAsWritten(null); + } + + handledUnknownValueFields.add(field); + } + + private List extractAnnotationTypes(AnalysisField field, UnknownObjectField unknownObjectField) { + List> annotationTypes = new ArrayList<>(Arrays.asList(unknownObjectField.types())); + for (String annotationTypeName : unknownObjectField.fullyQualifiedTypes()) { + try { + Class annotationType = Class.forName(annotationTypeName); + annotationTypes.add(annotationType); + } catch (ClassNotFoundException e) { + throw shouldNotReachHere("Annotation type not found " + annotationTypeName); + } + } + + List aAnnotationTypes = new ArrayList<>(); + AnalysisType declaredType = field.getType(); + + for (Class annotationType : annotationTypes) { + AnalysisType aAnnotationType = metaAccess.lookupJavaType(annotationType); + + assert !WordBase.class.isAssignableFrom(annotationType) : "Annotation type must not be a subtype of WordBase: field: " + field + " | declared type: " + declaredType + + " | annotation type: " + annotationType; + assert declaredType.isAssignableFrom(aAnnotationType) : "Annotation type must be a subtype of the declared type: field: " + field + " | declared type: " + declaredType + + " | annotation type: " + annotationType; + assert aAnnotationType.isArray() || (aAnnotationType.isInstanceClass() && !Modifier.isAbstract(aAnnotationType.getModifiers())) : "Annotation type failure: field: " + field + + " | annotation type " + aAnnotationType; + + aAnnotationTypes.add(aAnnotationType); + } + return aAnnotationTypes; + } + + /** + * Register a field as containing unknown object(s), i.e., is usually written only in hosted + * code. It can have multiple declared types provided via annotation. + */ + private void handleUnknownObjectField(AnalysisField aField, AnalysisType... declaredTypes) { + assert aField.getJavaKind() == JavaKind.Object; + + aField.registerAsWritten(null); + + /* Link the field with all declared types. */ + for (AnalysisType fieldDeclaredType : declaredTypes) { + markTypeReachable(fieldDeclaredType); + } + } + + private static Set filterUsedAnnotation(Set used, Annotation[] rest) { + if (rest == null) { + return null; + } + + Set restUsed = new HashSet<>(); + for (Annotation a : rest) { + if (used.contains(a)) { + restUsed.add(a); + } + } + return restUsed; + } + + public static Object encodeAnnotations(AnalysisMetaAccess metaAccess, Annotation[] allAnnotations, Annotation[] declaredAnnotations, Object oldEncoding) { + Object newEncoding; + if (allAnnotations.length == 0 && declaredAnnotations.length == 0) { + newEncoding = null; + } else { + Set all = new HashSet<>(); + Collections.addAll(all, allAnnotations); + Collections.addAll(all, declaredAnnotations); + final Set usedAnnotations = all.stream() + .filter(a -> { + try { + AnalysisType annotationClass = metaAccess.lookupJavaType(a.getClass()); + return isAnnotationUsed(annotationClass); + } catch (AnalysisError.TypeNotFoundError e) { + /* + * Silently ignore the annotation if its type was not discovered + * by the static analysis. + */ + return false; + } + }).collect(Collectors.toSet()); + Set usedDeclared = filterUsedAnnotation(usedAnnotations, declaredAnnotations); + newEncoding = usedAnnotations.size() == 0 + ? null + : AnnotationsEncoding.encodeAnnotations(usedAnnotations, usedDeclared); + } + + /* + * Return newEncoding only if the value is different from oldEncoding. Without this guard, + * for tests that do runtime compilation, the field appears as being continuously updated + * during BigBang.checkObjectGraph. + */ + if (oldEncoding != null && oldEncoding.equals(newEncoding)) { + return oldEncoding; + } else { + return newEncoding; + } + } + + /** + * We only want annotations in the native image heap that are "used" at run time. In our case, + * "used" means that the annotation interface is used at least in a type check. This leaves one + * case where Substrate VM behaves differently than a normal Java VM: When you just query the + * number of annotations on a class, then we might return a lower number. + */ + private static boolean isAnnotationUsed(AnalysisType annotationType) { + if (annotationType.isReachable()) { + return true; + } + assert annotationType.getInterfaces().length == 1 : annotationType; + + AnalysisType annotationInterfaceType = annotationType.getInterfaces()[0]; + return annotationInterfaceType.isReachable(); + } + + public static ResolvedJavaType toWrappedType(ResolvedJavaType type) { + if (type instanceof AnalysisType) { + return ((AnalysisType) type).getWrappedWithoutResolve(); + } else if (type instanceof HostedType) { + return ((HostedType) type).getWrapped().getWrappedWithoutResolve(); + } else { + return type; + } + } + } From e18fe7e5e8e4531376c9e983c662ca6144de57ce Mon Sep 17 00:00:00 2001 From: David Kozak Date: Mon, 11 Oct 2021 17:06:20 +0200 Subject: [PATCH 17/65] analyze the snippet graphs --- .../reachability/MethodSummaryProvider.java | 3 + .../reachability/ReachabilityAnalysis.java | 77 +++++++++++-------- .../SimpleInMemoryMethodSummaryProvider.java | 11 ++- .../svm/hosted/NativeImageGenerator.java | 12 ++- 4 files changed, 67 insertions(+), 36 deletions(-) diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummaryProvider.java index 710576e71db5..b7d0170d80ee 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummaryProvider.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummaryProvider.java @@ -26,7 +26,10 @@ import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.meta.AnalysisMethod; +import org.graalvm.compiler.nodes.StructuredGraph; public interface MethodSummaryProvider { MethodSummary getSummary(BigBang bigBang, AnalysisMethod method); + + MethodSummary getSummary(BigBang bigBang, StructuredGraph graph); } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index f508fda25a03..8201122259eb 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -39,6 +39,7 @@ import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import org.graalvm.compiler.debug.Indent; +import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.options.OptionValues; import java.util.Set; @@ -139,39 +140,7 @@ private void onMethodImplementationInvoked(AnalysisMethod method) { } try { MethodSummary summary = methodSummaryProvider.getSummary(this, method); - for (AnalysisMethod invokedMethod : summary.invokedMethods) { - markMethodInvoked(invokedMethod); - } - for (AnalysisMethod invokedMethod : summary.implementationInvokedMethods) { -// markMethodInvoked(invokedMethod); - markMethodImplementationInvoked(invokedMethod, method); - } - for (AnalysisType type : summary.accessedTypes) { - markTypeReachable(type); - } - for (AnalysisType type : summary.instantiatedTypes) { - markTypeInstantiated(type); - } - for (AnalysisField field : summary.readFields) { - markFieldRead(field); - } - for (AnalysisField field : summary.writtenFields) { - markFieldWritten(field); - } - for (JavaConstant constant : summary.embeddedConstants) { - if (constant.getJavaKind() == JavaKind.Object && constant.isNonNull()) { - // todo heap initiate scanning - // track the constant - if (this.scanningPolicy().trackConstant(this, constant)) { - BytecodePosition position = new BytecodePosition(null, method, 0); - getUniverse().registerEmbeddedRoot(constant, position); - - Object obj = getSnippetReflectionProvider().asObject(Object.class, constant); - AnalysisType type = getMetaAccess().lookupJavaType(obj.getClass()); - markTypeInHeap(type); - } - } - } + processSummary(method, summary); } catch (Throwable ex) { System.err.println("Failed to provide a summary for " + method.format("%H.%n(%p)")); System.err.println(ex + " " + ex.getMessage()); @@ -180,6 +149,42 @@ private void onMethodImplementationInvoked(AnalysisMethod method) { } } + private void processSummary(AnalysisMethod method, MethodSummary summary) { + for (AnalysisMethod invokedMethod : summary.invokedMethods) { + markMethodInvoked(invokedMethod); + } + for (AnalysisMethod invokedMethod : summary.implementationInvokedMethods) { +// markMethodInvoked(invokedMethod); + markMethodImplementationInvoked(invokedMethod, method); + } + for (AnalysisType type : summary.accessedTypes) { + markTypeReachable(type); + } + for (AnalysisType type : summary.instantiatedTypes) { + markTypeInstantiated(type); + } + for (AnalysisField field : summary.readFields) { + markFieldRead(field); + } + for (AnalysisField field : summary.writtenFields) { + markFieldWritten(field); + } + for (JavaConstant constant : summary.embeddedConstants) { + if (constant.getJavaKind() == JavaKind.Object && constant.isNonNull()) { + // todo heap initiate scanning + // track the constant + if (this.scanningPolicy().trackConstant(this, constant)) { + BytecodePosition position = new BytecodePosition(null, method, 0); + getUniverse().registerEmbeddedRoot(constant, position); + + Object obj = getSnippetReflectionProvider().asObject(Object.class, constant); + AnalysisType type = getMetaAccess().lookupJavaType(obj.getClass()); + markTypeInHeap(type); + } + } + } + } + @Override public void markFieldAccessed(AnalysisField field) { field.registerAsAccessed(); @@ -307,4 +312,10 @@ public TypeState getAllSynchronizedTypeState() { // todo don't overapproximate so much return objectType.getTypeFlow(this, true).getState(); } + + public void processGraph(StructuredGraph graph) { + MethodSummary summary = methodSummaryProvider.getSummary(this, graph); + // todo figure out what to pass + processSummary(null, summary); + } } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java index 1d6267044fda..681495316bc7 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java @@ -86,6 +86,15 @@ public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { // to preserve the graphs for compilation method.setAnalyzedGraph(decoded); + return createSummaryFromGraph(decoded); + } + + @Override + public MethodSummary getSummary(BigBang bigBang, StructuredGraph graph) { + return createSummaryFromGraph(graph); + } + + private MethodSummary createSummaryFromGraph(StructuredGraph graph) { List accessedTypes = new ArrayList<>(); List instantiatedTypes = new ArrayList<>(); List readFields = new ArrayList<>(); @@ -93,7 +102,7 @@ public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { List invokedMethods = new ArrayList<>(); List implementationInvokedMethods = new ArrayList<>(); List embeddedConstants = new ArrayList<>(); - for (Node n : decoded.getNodes()) { + for (Node n : graph.getNodes()) { if (n instanceof NewInstanceNode) { NewInstanceNode node = (NewInstanceNode) n; instantiatedTypes.add(analysisType(node.instanceClass())); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index 8c7d2aa6370e..8d50ac35fd9e 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -1010,11 +1010,19 @@ public static void initializeBigBang(Inflation bb, OptionValues options, Feature bb.getAnnotationSubstitutionProcessor(), classInitializationPlugin, bb.getHostVM().getClassInitializationSupport(), ConfigurationValues.getTarget()); registerReplacements(debug, featureHandler, null, aProviders, true, initForeignCalls); + Collection snippetGraphs = aReplacements.getSnippetGraphs(GraalOptions.TrackNodeSourcePosition.getValue(options), options); + // todo refactor if (bb instanceof NativeImagePointsToAnalysis) { - // todo refactor - for (StructuredGraph graph : aReplacements.getSnippetGraphs(GraalOptions.TrackNodeSourcePosition.getValue(options), options)) { + for (StructuredGraph graph : snippetGraphs) { HostedConfiguration.instance().createMethodTypeFlowBuilder(((NativeImagePointsToAnalysis) bb), graph).registerUsedElements(false); } + } else if (bb instanceof NativeImageReachabilityAnalysis) { + NativeImageReachabilityAnalysis reachabilityAnalysis = (NativeImageReachabilityAnalysis) bb; + for (StructuredGraph graph : snippetGraphs) { + reachabilityAnalysis.processGraph(graph); + } + } else { + throw VMError.shouldNotReachHere("Unknown analysis type - please specify how to handle snippets"); } } } From 8755ba92b0722a062d36e8ecf035e1e86d5b94df Mon Sep 17 00:00:00 2001 From: David Kozak Date: Tue, 12 Oct 2021 23:26:46 +0200 Subject: [PATCH 18/65] wip --- .../graal/pointsto/api/PointstoOptions.java | 2 +- .../graal/reachability/MethodSummary.java | 4 + .../reachability/ReachabilityAnalysis.java | 48 +++++++++- .../svm/hosted/NativeImageGenerator.java | 93 +++++++++++++++++++ 4 files changed, 143 insertions(+), 4 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/PointstoOptions.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/PointstoOptions.java index 0986e8ddb718..ee030e023e36 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/PointstoOptions.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/PointstoOptions.java @@ -81,7 +81,7 @@ public class PointstoOptions { public static final OptionKey ExtendedAsserts = new OptionKey<>(false); @Option(help = "Track the callers for methods and accessing methods for fields.")// - public static final OptionKey TrackAccessChain = new OptionKey<>(false); + public static final OptionKey TrackAccessChain = new OptionKey<>(true); @Option(help = "Track the input for type flows.")// public static final OptionKey TrackInputFlows = new OptionKey<>(false); diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java index e9b2a5cbe416..29db59c95fdc 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java @@ -67,4 +67,8 @@ public String toString() { ", embeddedConstants=" + Arrays.toString(embeddedConstants) + '}'; } + + public MethodSummary withoutMethods() { + return new MethodSummary(new AnalysisMethod[0], new AnalysisMethod[0], accessedTypes, instantiatedTypes, readFields, writtenFields, embeddedConstants); + } } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index 8201122259eb..84c562844459 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -38,10 +38,18 @@ import jdk.vm.ci.code.BytecodePosition; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.debug.Indent; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.extended.ForeignCall; import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode; +import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode; +import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ForkJoinPool; @@ -154,7 +162,7 @@ private void processSummary(AnalysisMethod method, MethodSummary summary) { markMethodInvoked(invokedMethod); } for (AnalysisMethod invokedMethod : summary.implementationInvokedMethods) { -// markMethodInvoked(invokedMethod); + markMethodInvoked(invokedMethod); markMethodImplementationInvoked(invokedMethod, method); } for (AnalysisType type : summary.accessedTypes) { @@ -315,7 +323,41 @@ public TypeState getAllSynchronizedTypeState() { public void processGraph(StructuredGraph graph) { MethodSummary summary = methodSummaryProvider.getSummary(this, graph); - // todo figure out what to pass - processSummary(null, summary); + AnalysisMethod method = analysisMethod(graph.method()); + method.registerAsInvoked(null); + method.registerAsImplementationInvoked(null); + processSummary(method, summary.withoutMethods()); + + registerForeignCalls(graph); + } + + private void registerForeignCalls(StructuredGraph graph) { + for (Node n : graph.getNodes()) { + if (n instanceof ForeignCall) { + ForeignCall node = (ForeignCall) n; + registerForeignCall(node.getDescriptor()); + } else if (n instanceof UnaryMathIntrinsicNode) { + UnaryMathIntrinsicNode node = (UnaryMathIntrinsicNode) n; + registerForeignCall(getProviders().getForeignCalls().getDescriptor(node.getOperation().foreignCallSignature)); + } else if (n instanceof BinaryMathIntrinsicNode) { + BinaryMathIntrinsicNode node = (BinaryMathIntrinsicNode) n; + registerForeignCall(getProviders().getForeignCalls().getDescriptor(node.getOperation().foreignCallSignature)); + } else if (n instanceof FrameState) { + FrameState node = (FrameState) n; + AnalysisMethod method = (AnalysisMethod) node.getMethod(); + if (method != null) { + markTypeReachable(method.getDeclaringClass()); + } + } + } + } + + private void registerForeignCall(ForeignCallDescriptor descriptor) { + Optional targetMethod = getHostVM().handleForeignCall(descriptor, getProviders().getForeignCalls()); + targetMethod.ifPresent(this::addRootMethod); + } + + private AnalysisMethod analysisMethod(ResolvedJavaMethod method) { + return method instanceof AnalysisMethod ? ((AnalysisMethod) method) : universe.lookup(method); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index 8d50ac35fd9e..7e6ca0d0ca3c 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -30,6 +30,8 @@ import static org.graalvm.compiler.hotspot.JVMCIVersionCheck.JVMCI8_RELEASES_URL; import static org.graalvm.compiler.replacements.StandardGraphBuilderPlugins.registerInvocationPlugins; +import java.io.File; +import java.io.FileWriter; import java.io.IOException; import java.lang.ref.Reference; import java.lang.reflect.Method; @@ -46,6 +48,7 @@ import java.util.Comparator; import java.util.EnumMap; import java.util.EnumSet; +import java.util.HashSet; import java.util.List; import java.util.ListIterator; import java.util.Map; @@ -59,6 +62,7 @@ import com.oracle.graal.pointsto.PointsToAnalysis; import com.oracle.graal.pointsto.meta.PointsToAnalysisFactory; import com.oracle.graal.pointsto.meta.PointsToAnalysisMethod; +import com.oracle.graal.pointsto.infrastructure.WrappedElement; import com.oracle.graal.reachability.SimpleInMemoryMethodSummaryProvider; import com.oracle.svm.core.code.ImageCodeInfo; import com.oracle.svm.hosted.analysis.NativeImageReachabilityAnalysis; @@ -550,6 +554,8 @@ private void doRun(Map entryPoints, return; } + dumpAnalysisStats(); + NativeImageHeap heap; HostedMetaAccess hMetaAccess; SharedRuntimeConfigurationBuilder runtime; @@ -699,6 +705,93 @@ private void doRun(Map entryPoints, } } + private static final String DUMP_FOLDER = "/Users/dkozak/tmp/hello-dir/stats/"; + + private void dumpAnalysisStats() { + AnalysisUniverse universe = getBigbang().getUniverse(); + List reachableTypes = universe.getTypes().stream().filter(AnalysisType::isReachable).map(AnalysisType::getName).sorted().collect(Collectors.toList()); + List invokedMethods = universe.getMethods().stream().filter(AnalysisMethod::isInvoked).map(it -> it.format("%H.%n(%P)")).sorted().collect(Collectors.toList()); + List implInvokedMethods = universe.getMethods().stream().filter(AnalysisMethod::isImplementationInvoked).map(it -> it.format("%H.%n(%P)")).sorted().collect(Collectors.toList()); + System.out.println("Reachable types " + reachableTypes.size()); + System.out.println("Invoked methods " + invokedMethods.size()); + System.out.println("Implementation invoked methods " + implInvokedMethods.size()); + + boolean useReachability = NativeImageOptions.UseExperimentalReachabilityAnalysis.getValue(); + String fileName = useReachability ? "reachability_" : "points-to_"; + + List, String>> pairs = Arrays.asList(Pair.create(reachableTypes, "types"), Pair.create(invokedMethods, "invokedMethods"), + Pair.create(implInvokedMethods, "implInvokedMethods")); + + for (Pair, String> pair : pairs) { + try (FileWriter writer = new FileWriter(DUMP_FOLDER + fileName + pair.getRight())) { + for (String line : pair.getLeft()) { + writer.write(line); + writer.write('\n'); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + private String dumpChain(AnalysisMethod method) { + ArrayList methods = new ArrayList<>(); + Set seen = new HashSet<>(); + + boolean success = dfs(method, methods, seen); + StringBuilder builder = new StringBuilder(); + if (!success) { + builder.append("Path is incomplete :X \n"); + } + return serializePath(methods, builder); + } + + private String serializePath(ArrayList methods, StringBuilder builder) { + for (int i = methods.size() - 1; i >= 0; i--) { + builder.append(methods.get(i)); + if (i != 0) + builder.append("->"); + } + return builder.toString(); + } + + private boolean dfs(AnalysisMethod method, ArrayList methods, Set seen) { + String name = method.format("%H.%n(%P)"); + if (!seen.add(name)) { + return false; + } + methods.add(name); + if (method.isRootMethod()) { + return true; + } + Set callers = method.getCallers(); + for (AnalysisMethod caller : callers) { + if (dfs(caller, methods, seen)) { + return true; + } + } + if (callers.isEmpty()) { + System.out.println(serializePath(methods, new StringBuilder())); + } + methods.remove(methods.size() - 1); + return false; + } + + void reportBuildArtifacts(String imageName) { + Path buildDir = generatedFiles(HostedOptionValues.singleton()); + Consumer writerConsumer = writer -> buildArtifacts.forEach((artifactType, paths) -> { + writer.println("[" + artifactType + "]"); + if (artifactType == BuildArtifacts.ArtifactType.JDK_LIB_SHIM) { + writer.println("# Note that shim JDK libraries depend on this"); + writer.println("# particular native image (including its name)"); + writer.println("# and therefore cannot be used with others."); + } + paths.stream().map(Path::toAbsolutePath).map(buildDir::relativize).forEach(writer::println); + writer.println(); + }); + ReportUtils.report("build artifacts", buildDir.resolve(imageName + ".build_artifacts.txt"), writerConsumer); + } + @SuppressWarnings("try") private boolean runPointsToAnalysis(String imageName, OptionValues options, DebugContext debug) { try (Indent ignored = debug.logAndIndent("run analysis")) { From c2f78f309df498ce7c9a22748b02f160d4729d95 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Thu, 14 Oct 2021 14:43:10 +0200 Subject: [PATCH 19/65] use AnalysisType.forAllSuperTypes when handling instantiation to ensure that interfaces are taken into account --- .../graal/pointsto/meta/AnalysisType.java | 6 +-- .../graal/pointsto/meta/AnalysisUniverse.java | 15 ++---- .../reachability/ReachabilityAnalysis.java | 12 +++-- .../svm/hosted/NativeImageGenerator.java | 54 ++++++++++++++++++- 4 files changed, 64 insertions(+), 23 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java index 30d977a9b0a8..64355d0b696d 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java @@ -448,11 +448,7 @@ private void registerAsInstantiated(UsageKind usageKind) { assert isArray() || (isInstanceClass() && !Modifier.isAbstract(getModifiers())) : this; universe.hostVM.checkForbidden(this, usageKind); - AnalysisType current = this; - while (current != null) { - current.instantiatedSubtypes.add(this); - current = current.getSuperclass(); - } + forAllSuperTypes(t -> t.instantiatedSubtypes.add(this)); } /** diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java index 961bdde4f01d..24b76be614d2 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java @@ -184,10 +184,7 @@ public AnalysisType optionalLookup(ResolvedJavaType type) { @Override public AnalysisType lookup(JavaType type) { - if (type instanceof AnalysisType) { - System.err.println("Querying already made analysis type: " + type); - return ((AnalysisType) type); - } + assert !(type instanceof AnalysisType) : "Must not a lookup a type that already is an AnalysisType: " + type; JavaType result = lookupAllowUnresolved(type); if (result == null) { return null; @@ -347,10 +344,7 @@ public JavaKind getStorageKind(ResolvedJavaType type, MetaAccessProvider metaAcc @Override public AnalysisField lookup(JavaField field) { - if (field instanceof AnalysisField) { - System.err.println("Querying already made analysis field: " + field); - return ((AnalysisField) field); - } + assert !(field instanceof AnalysisField) : "Must not a lookup a field that already is an AnalysisField: " + field; JavaField result = lookupAllowUnresolved(field); if (result == null) { return null; @@ -408,10 +402,7 @@ private AnalysisField createField(ResolvedJavaField field) { @Override public AnalysisMethod lookup(JavaMethod method) { - if (method instanceof AnalysisMethod) { - System.err.println("Querying already made analysis method: " + method); - return ((AnalysisMethod) method); - } + assert !(method instanceof AnalysisMethod) : "Must not a lookup a method that already is an AnalysisMethod: " + method; JavaMethod result = lookupAllowUnresolved(method); if (result == null) { return null; diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index 84c562844459..a1df1bab0421 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -49,6 +49,7 @@ import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode; import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -133,6 +134,8 @@ public void markMethodImplementationInvoked(AnalysisMethod method, Object reason private static final Set processed = ConcurrentHashMap.newKeySet(); private static final Set processed2 = ConcurrentHashMap.newKeySet(); + public final Map summaries = new ConcurrentHashMap<>(); + private void onMethodImplementationInvoked(AnalysisMethod method) { if (!processed.add(method)) { System.err.println("Method " + method + " has already been processed"); @@ -149,6 +152,7 @@ private void onMethodImplementationInvoked(AnalysisMethod method) { try { MethodSummary summary = methodSummaryProvider.getSummary(this, method); processSummary(method, summary); + summaries.put(method, summary); } catch (Throwable ex) { System.err.println("Failed to provide a summary for " + method.format("%H.%n(%p)")); System.err.println(ex + " " + ex.getMessage()); @@ -224,8 +228,7 @@ public void markTypeInstantiated(AnalysisType type) { if (!type.registerAsAllocated(null)) { return; } - AnalysisType current = type; - while (current != null) { + type.forAllSuperTypes(current -> { Set invokedMethods = current.getInvokedMethods(); for (AnalysisMethod method : invokedMethods) { AnalysisMethod implementationInvokedMethod = type.resolveConcreteMethod(method, current); @@ -234,10 +237,9 @@ public void markTypeInstantiated(AnalysisType type) { continue; } markMethodImplementationInvoked(implementationInvokedMethod, type); // todo better - // reason + // reason } - current = current.getSuperclass(); - } + }); } private void markMethodInvoked(AnalysisMethod method) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index 7e6ca0d0ca3c..05bfe5c256c4 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -63,6 +63,7 @@ import com.oracle.graal.pointsto.meta.PointsToAnalysisFactory; import com.oracle.graal.pointsto.meta.PointsToAnalysisMethod; import com.oracle.graal.pointsto.infrastructure.WrappedElement; +import com.oracle.graal.reachability.MethodSummary; import com.oracle.graal.reachability.SimpleInMemoryMethodSummaryProvider; import com.oracle.svm.core.code.ImageCodeInfo; import com.oracle.svm.hosted.analysis.NativeImageReachabilityAnalysis; @@ -732,6 +733,56 @@ private void dumpAnalysisStats() { e.printStackTrace(); } } + + try (FileWriter writer = new FileWriter(DUMP_FOLDER + fileName + "invokeStats")) { + List implInvoked = universe.getMethods().stream().filter(AnalysisMethod::isImplementationInvoked).collect(Collectors.toList()); + for (AnalysisMethod method : implInvoked) { + writer.write(method.format("%H.%n(%P)")); + writer.write(','); + List callees = getCallees(method); + writer.write(Integer.toString(callees.size())); + writer.write('\n'); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + private List getCallees(AnalysisMethod method) { + if (bb instanceof NativeImageReachabilityAnalysis) { + return getCalleesR(((NativeImageReachabilityAnalysis) bb), method); + } else if (bb instanceof NativeImagePointsToAnalysis) { + return getCalleesP((NativeImagePointsToAnalysis) bb, method); + } + throw VMError.shouldNotReachHere(); + } + + private List getCalleesP(NativeImagePointsToAnalysis bb, AnalysisMethod method) { + return method.getTypeFlow().getInvokes().stream().flatMap(it -> it.getCallees().stream()).collect(Collectors.toList()); + } + + private List getCalleesR(NativeImageReachabilityAnalysis bb, AnalysisMethod method) { + MethodSummary summary = bb.summaries.get(method); + if (summary == null) { + System.err.println("Don't have a summary for " + method); + return Collections.emptyList(); + } + List callees = new ArrayList<>(); + Collections.addAll(callees, summary.implementationInvokedMethods); + for (AnalysisMethod invokedMethod : summary.invokedMethods) { + AnalysisType clazz = invokedMethod.getDeclaringClass(); + // todo solve instantiated subtypes with interfaces! + // java.util.Collections$UnmodifiableList.equals(java.lang.Object) + // java.util.List.equals + // declaring type is List - interface - has no instantiated subtypes atm + for (AnalysisType subtype : clazz.getInstantiatedSubtypes()) { + AnalysisMethod resolved = subtype.resolveConcreteMethod(invokedMethod, clazz); + if (resolved != null) { + callees.add(resolved); + } + } + } + return callees; } private String dumpChain(AnalysisMethod method) { @@ -749,8 +800,9 @@ private String dumpChain(AnalysisMethod method) { private String serializePath(ArrayList methods, StringBuilder builder) { for (int i = methods.size() - 1; i >= 0; i--) { builder.append(methods.get(i)); - if (i != 0) + if (i != 0) { builder.append("->"); + } } return builder.toString(); } From fa4b470e5b4f5c6abb1033069211edfba1a3ee94 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Fri, 15 Oct 2021 14:13:39 +0200 Subject: [PATCH 20/65] handle CopyOf and CopyOfRange nodes --- .../SimpleInMemoryMethodSummaryProvider.java | 149 ++++++++++-------- .../svm/hosted/HostedConfiguration.java | 8 + .../svm/hosted/NativeImageGenerator.java | 3 +- 3 files changed, 89 insertions(+), 71 deletions(-) diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java index 681495316bc7..6218d3cfcce3 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java @@ -27,6 +27,7 @@ import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.flow.AnalysisParsedGraph; import com.oracle.graal.pointsto.meta.AnalysisField; +import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.meta.AnalysisUniverse; @@ -55,10 +56,12 @@ public class SimpleInMemoryMethodSummaryProvider implements MethodSummaryProvider { - private final AnalysisUniverse universe; + protected final AnalysisUniverse universe; + protected final AnalysisMetaAccess metaAccess; - public SimpleInMemoryMethodSummaryProvider(AnalysisUniverse universe) { + public SimpleInMemoryMethodSummaryProvider(AnalysisUniverse universe, AnalysisMetaAccess metaAccess) { this.universe = universe; + this.metaAccess = metaAccess; } @Override @@ -86,79 +89,15 @@ public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { // to preserve the graphs for compilation method.setAnalyzedGraph(decoded); - return createSummaryFromGraph(decoded); + return new Instance().createSummaryFromGraph(decoded); } @Override public MethodSummary getSummary(BigBang bigBang, StructuredGraph graph) { - return createSummaryFromGraph(graph); + return new Instance().createSummaryFromGraph(graph); } - private MethodSummary createSummaryFromGraph(StructuredGraph graph) { - List accessedTypes = new ArrayList<>(); - List instantiatedTypes = new ArrayList<>(); - List readFields = new ArrayList<>(); - List writtenFields = new ArrayList<>(); - List invokedMethods = new ArrayList<>(); - List implementationInvokedMethods = new ArrayList<>(); - List embeddedConstants = new ArrayList<>(); - for (Node n : graph.getNodes()) { - if (n instanceof NewInstanceNode) { - NewInstanceNode node = (NewInstanceNode) n; - instantiatedTypes.add(analysisType(node.instanceClass())); - } else if (n instanceof NewArrayNode) { - NewArrayNode node = (NewArrayNode) n; - instantiatedTypes.add(analysisType(node.elementType()).getArrayClass()); - } else if (n instanceof NewMultiArrayNode) { - NewMultiArrayNode node = (NewMultiArrayNode) n; - ResolvedJavaType type = node.type(); - for (int i = 0; i < node.dimensionCount(); i++) { - instantiatedTypes.add(analysisType(type)); - type = type.getComponentType(); - } - } else if (n instanceof ConstantNode) { - ConstantNode node = (ConstantNode) n; - if (!(node.getValue() instanceof JavaConstant)) { - /* - * The bytecode parser sometimes embeds low-level VM constants for types into - * the high-level graph. Since these constants are the result of type lookups, - * these types are already marked as reachable. Eventually, the bytecode parser - * should be changed to only use JavaConstant. - */ - continue; - } - embeddedConstants.add(((JavaConstant) node.getValue())); - } else if (n instanceof InstanceOfNode) { - InstanceOfNode node = (InstanceOfNode) n; - accessedTypes.add(analysisType(node.type().getType())); - } else if (n instanceof AccessFieldNode) { - if (n instanceof LoadFieldNode) { - LoadFieldNode node = (LoadFieldNode) n; - readFields.add(analysisField(node.field())); - } else if (n instanceof StoreFieldNode) { - StoreFieldNode node = (StoreFieldNode) n; - writtenFields.add(analysisField(node.field())); - } else { - throw AnalysisError.shouldNotReachHere("Unhalded AccessFieldNode Type"); - } - } else if (n instanceof Invoke) { - Invoke node = (Invoke) n; - CallTargetNode.InvokeKind kind = node.getInvokeKind(); - AnalysisMethod targetMethod = analysisMethod(node.getTargetMethod()); - if (targetMethod == null) { - continue; - } - if (kind.isDirect()) { - implementationInvokedMethods.add(targetMethod); - } else { - invokedMethods.add(targetMethod); - } - } - } - return new MethodSummary(invokedMethods.toArray(new AnalysisMethod[0]), implementationInvokedMethods.toArray(new AnalysisMethod[0]), - accessedTypes.toArray(new AnalysisType[0]), - instantiatedTypes.toArray(new AnalysisType[0]), readFields.toArray(new AnalysisField[0]), writtenFields.toArray(new AnalysisField[0]), - embeddedConstants.toArray(new JavaConstant[0])); + protected void delegateNodeProcessing(Instance instance, Node node) { } private AnalysisType analysisType(ResolvedJavaType type) { @@ -172,4 +111,76 @@ private AnalysisMethod analysisMethod(ResolvedJavaMethod method) { private AnalysisField analysisField(ResolvedJavaField field) { return field instanceof AnalysisField ? ((AnalysisField) field) : universe.lookup(field); } + + protected class Instance { + public final List accessedTypes = new ArrayList<>(); + public final List instantiatedTypes = new ArrayList<>(); + public final List readFields = new ArrayList<>(); + public final List writtenFields = new ArrayList<>(); + public final List invokedMethods = new ArrayList<>(); + public final List implementationInvokedMethods = new ArrayList<>(); + public final List embeddedConstants = new ArrayList<>(); + + private MethodSummary createSummaryFromGraph(StructuredGraph graph) { + + for (Node n : graph.getNodes()) { + if (n instanceof NewInstanceNode) { + NewInstanceNode node = (NewInstanceNode) n; + instantiatedTypes.add(analysisType(node.instanceClass())); + } else if (n instanceof NewArrayNode) { + NewArrayNode node = (NewArrayNode) n; + instantiatedTypes.add(analysisType(node.elementType()).getArrayClass()); + } else if (n instanceof NewMultiArrayNode) { + NewMultiArrayNode node = (NewMultiArrayNode) n; + ResolvedJavaType type = node.type(); + for (int i = 0; i < node.dimensionCount(); i++) { + instantiatedTypes.add(analysisType(type)); + type = type.getComponentType(); + } + } else if (n instanceof ConstantNode) { + ConstantNode node = (ConstantNode) n; + if (!(node.getValue() instanceof JavaConstant)) { + /* + * The bytecode parser sometimes embeds low-level VM constants for types + * into the high-level graph. Since these constants are the result of type + * lookups, these types are already marked as reachable. Eventually, the + * bytecode parser should be changed to only use JavaConstant. + */ + continue; + } + embeddedConstants.add(((JavaConstant) node.getValue())); + } else if (n instanceof InstanceOfNode) { + InstanceOfNode node = (InstanceOfNode) n; + accessedTypes.add(analysisType(node.type().getType())); + } else if (n instanceof AccessFieldNode) { + if (n instanceof LoadFieldNode) { + LoadFieldNode node = (LoadFieldNode) n; + readFields.add(analysisField(node.field())); + } else if (n instanceof StoreFieldNode) { + StoreFieldNode node = (StoreFieldNode) n; + writtenFields.add(analysisField(node.field())); + } else { + throw AnalysisError.shouldNotReachHere("Unhalded AccessFieldNode Type"); + } + } else if (n instanceof Invoke) { + Invoke node = (Invoke) n; + CallTargetNode.InvokeKind kind = node.getInvokeKind(); + AnalysisMethod targetMethod = analysisMethod(node.getTargetMethod()); + if (targetMethod == null) { + continue; + } + if (kind.isDirect()) { + implementationInvokedMethods.add(targetMethod); + } else { + invokedMethods.add(targetMethod); + } + } + delegateNodeProcessing(this, n); + } + return new MethodSummary(invokedMethods.toArray(new AnalysisMethod[0]), implementationInvokedMethods.toArray(new AnalysisMethod[0]), + accessedTypes.toArray(new AnalysisType[0]), + instantiatedTypes.toArray(new AnalysisType[0]), readFields.toArray(new AnalysisField[0]), writtenFields.toArray(new AnalysisField[0]), + embeddedConstants.toArray(new JavaConstant[0])); + } + } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java index 916d5cf5a502..2d2f5e848daa 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java @@ -32,7 +32,11 @@ import java.util.concurrent.ForkJoinPool; import com.oracle.graal.pointsto.BigBang; +import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; +import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.graal.pointsto.results.DummyResultsBuilder; +import com.oracle.graal.reachability.MethodSummaryProvider; +import com.oracle.graal.reachability.SimpleInMemoryMethodSummaryProvider; import com.oracle.svm.hosted.analysis.Inflation; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.CompressEncoding; @@ -154,6 +158,10 @@ public MethodTypeFlowBuilder createMethodTypeFlowBuilder(PointsToAnalysis bb, St return new SVMMethodTypeFlowBuilder(bb, graph); } + public MethodSummaryProvider createMethodSummaryProvider(AnalysisUniverse universe, AnalysisMetaAccess aMetaAccess) { + return new SimpleInMemoryMethodSummaryProvider(universe, aMetaAccess); + } + public void findAllFieldsForLayout(HostedUniverse universe, @SuppressWarnings("unused") HostedMetaAccess metaAccess, @SuppressWarnings("unused") Map universeFields, ArrayList rawFields, diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index 05bfe5c256c4..cc08646a79e4 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -64,7 +64,6 @@ import com.oracle.graal.pointsto.meta.PointsToAnalysisMethod; import com.oracle.graal.pointsto.infrastructure.WrappedElement; import com.oracle.graal.reachability.MethodSummary; -import com.oracle.graal.reachability.SimpleInMemoryMethodSummaryProvider; import com.oracle.svm.core.code.ImageCodeInfo; import com.oracle.svm.hosted.analysis.NativeImageReachabilityAnalysis; import org.graalvm.collections.EconomicSet; @@ -1198,7 +1197,7 @@ public static Inflation createBigBang(OptionValues options, TargetDescription ta if (NativeImageOptions.UseExperimentalReachabilityAnalysis.getValue()) { return new NativeImageReachabilityAnalysis(options, aUniverse, aProviders, annotationSubstitutionProcessor, analysisExecutor, heartbeatCallback, - new SimpleInMemoryMethodSummaryProvider(aUniverse)); + HostedConfiguration.instance().createMethodSummaryProvider(aUniverse, aMetaAccess)); } return new NativeImagePointsToAnalysis(options, aUniverse, aProviders, annotationSubstitutionProcessor, analysisExecutor, heartbeatCallback, new SubstrateUnsupportedFeatures()); } From 2e9010c91c4a5c351c55eba4270e98ee097562db Mon Sep 17 00:00:00 2001 From: David Kozak Date: Fri, 15 Oct 2021 16:35:05 +0200 Subject: [PATCH 21/65] handle embedded FrameStates --- .../reachability/SimpleInMemoryMethodSummaryProvider.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java index 6218d3cfcce3..b34525647e1e 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java @@ -40,6 +40,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.CallTargetNode; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.java.AccessFieldNode; @@ -174,6 +175,13 @@ private MethodSummary createSummaryFromGraph(StructuredGraph graph) { } else { invokedMethods.add(targetMethod); } + } else if (n instanceof FrameState) { + FrameState node = (FrameState) n; + ResolvedJavaMethod method = node.getMethod(); + if (method != null) { + AnalysisMethod analysisMethod = analysisMethod(method); + accessedTypes.add(analysisMethod.getDeclaringClass()); + } } delegateNodeProcessing(this, n); } From 07c8f016d8f5145c2697294d0e852ee087ccf2de Mon Sep 17 00:00:00 2001 From: David Kozak Date: Fri, 15 Oct 2021 17:46:25 +0200 Subject: [PATCH 22/65] cleanup --- .../pointsto/AbstractAnalysisEngine.java | 3 ++- .../reachability/ReachabilityAnalysis.java | 24 +++++++------------ .../SimpleInMemoryMethodSummaryProvider.java | 18 +++++++------- .../svm/hosted/NativeImageGenerator.java | 2 +- 4 files changed, 21 insertions(+), 26 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java index 8ee601d49ff9..9d2edbf78aaa 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java @@ -80,7 +80,8 @@ public AbstractAnalysisEngine(OptionValues options, AnalysisUniverse universe, H this.hostVM = hostVM; this.executorService = executorService; this.executor = new CompletionExecutor(this, executorService, heartbeatCallback); - this.timing = new AnalysisTiming(); + // todo specify timing via option + this.timing = null; this.executor.init(timing); this.heartbeatCallback = heartbeatCallback; this.unsupportedFeatures = unsupportedFeatures; diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index a1df1bab0421..477fec096bcf 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -131,24 +131,9 @@ public void markMethodImplementationInvoked(AnalysisMethod method, Object reason schedule(() -> onMethodImplementationInvoked(method)); } - private static final Set processed = ConcurrentHashMap.newKeySet(); - private static final Set processed2 = ConcurrentHashMap.newKeySet(); - public final Map summaries = new ConcurrentHashMap<>(); private void onMethodImplementationInvoked(AnalysisMethod method) { - if (!processed.add(method)) { - System.err.println("Method " + method + " has already been processed"); -// return; - } - if (!processed2.add(method.getQualifiedName())) { - System.err.println("Method " + method + " has already been processed"); -// return; - } - if (method.isNative()) { - System.err.println("native method " + method); -// return; - } try { MethodSummary summary = methodSummaryProvider.getSummary(this, method); processSummary(method, summary); @@ -231,6 +216,9 @@ public void markTypeInstantiated(AnalysisType type) { type.forAllSuperTypes(current -> { Set invokedMethods = current.getInvokedMethods(); for (AnalysisMethod method : invokedMethods) { + if (method.isStatic()) { + continue; + } AnalysisMethod implementationInvokedMethod = type.resolveConcreteMethod(method, current); if (implementationInvokedMethod == null) { System.out.println("onMethodInvoked: method " + method + " on type " + current + " is null"); @@ -252,6 +240,11 @@ private void markMethodInvoked(AnalysisMethod method) { private void onMethodInvoked(AnalysisMethod method) { AnalysisType clazz = method.getDeclaringClass(); Set instantiatedSubtypes = clazz.getInstantiatedSubtypes(); + if (method.isStatic()) { + // todo better reason + markMethodImplementationInvoked(method, null); + return; + } for (AnalysisType subtype : instantiatedSubtypes) { AnalysisMethod resolvedMethod = subtype.resolveConcreteMethod(method, clazz); if (resolvedMethod == null) { @@ -335,6 +328,7 @@ public void processGraph(StructuredGraph graph) { private void registerForeignCalls(StructuredGraph graph) { for (Node n : graph.getNodes()) { + // todo handle foreign calls even in the summary provider? if (n instanceof ForeignCall) { ForeignCall node = (ForeignCall) n; registerForeignCall(node.getDescriptor()); diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java index b34525647e1e..c020427bcba9 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java @@ -50,7 +50,7 @@ import org.graalvm.compiler.nodes.java.NewInstanceNode; import org.graalvm.compiler.nodes.java.NewMultiArrayNode; import org.graalvm.compiler.nodes.java.StoreFieldNode; -import org.graalvm.util.GuardedAnnotationAccess; +import org.graalvm.compiler.replacements.nodes.MacroInvokable; import java.util.ArrayList; import java.util.List; @@ -67,19 +67,11 @@ public SimpleInMemoryMethodSummaryProvider(AnalysisUniverse universe, AnalysisMe @Override public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { - if (method.isIntrinsicMethod()) { - System.err.println("this is intrinsic: " + method); -// return MethodSummary.EMPTY; - } AnalysisParsedGraph analysisParsedGraph = method.ensureGraphParsed(bb); if (analysisParsedGraph.getEncodedGraph() == null) { System.err.println("Encoded empty for " + method); return MethodSummary.EMPTY; } - if (GuardedAnnotationAccess.isAnnotationPresent(method, Node.NodeIntrinsic.class)) { - System.err.println("parsing an intrinsic: " + method); -// return MethodSummary.EMPTY; - } StructuredGraph decoded = InlineBeforeAnalysis.decodeGraph(bb, method, analysisParsedGraph); @@ -182,6 +174,14 @@ private MethodSummary createSummaryFromGraph(StructuredGraph graph) { AnalysisMethod analysisMethod = analysisMethod(method); accessedTypes.add(analysisMethod.getDeclaringClass()); } + } else if (n instanceof MacroInvokable) { + MacroInvokable node = (MacroInvokable) n; + AnalysisMethod targetMethod = analysisMethod(node.getTargetMethod()); + if (node.getInvokeKind().isDirect()) { + implementationInvokedMethods.add(targetMethod); + } else { + invokedMethods.add(targetMethod); + } } delegateNodeProcessing(this, n); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index cc08646a79e4..5cd06e3173ee 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -763,7 +763,7 @@ private List getCalleesP(NativeImagePointsToAnalysis bb, Analysi private List getCalleesR(NativeImageReachabilityAnalysis bb, AnalysisMethod method) { MethodSummary summary = bb.summaries.get(method); if (summary == null) { - System.err.println("Don't have a summary for " + method); +// System.err.println("Don't have a summary for " + method); return Collections.emptyList(); } List callees = new ArrayList<>(); From baad44ae8acc1af72271e5a4d13fdedb0873002f Mon Sep 17 00:00:00 2001 From: David Kozak Date: Fri, 15 Oct 2021 17:46:58 +0200 Subject: [PATCH 23/65] add uninterruptible annotations to RegisterDumper and UContextRegisterDumper --- .../src/com/oracle/svm/core/posix/UContextRegisterDumper.java | 2 ++ .../src/com/oracle/svm/core/RegisterDumper.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/UContextRegisterDumper.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/UContextRegisterDumper.java index 593c0307eb04..f32d569e45fd 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/UContextRegisterDumper.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/UContextRegisterDumper.java @@ -34,8 +34,10 @@ public interface UContextRegisterDumper extends RegisterDumper { void dumpRegisters(Log log, ucontext_t uContext, boolean printLocationInfo, boolean allowJavaHeapAccess, boolean allowUnsafeOperations); + @Uninterruptible(reason = "Called from uninterruptible code.") PointerBase getHeapBase(ucontext_t uContext); + @Uninterruptible(reason = "Called from uninterruptible code.") PointerBase getThreadPointer(ucontext_t uContext); PointerBase getSP(ucontext_t uContext); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/RegisterDumper.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/RegisterDumper.java index c9774ee878da..36a780f80ae2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/RegisterDumper.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/RegisterDumper.java @@ -55,8 +55,10 @@ interface Context extends PointerBase { void dumpRegisters(Log log, Context context, boolean printLocationInfo, boolean allowJavaHeapAccess, boolean allowUnsafeOperations); + @Uninterruptible(reason = "Called from uninterruptible code.") PointerBase getHeapBase(Context context); + @Uninterruptible(reason = "Called from uninterruptible code.") PointerBase getThreadPointer(Context context); PointerBase getSP(Context context); From fb5500a9e61d11f431b078cd4ddcced3a0f51144 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Mon, 18 Oct 2021 11:33:56 +0200 Subject: [PATCH 24/65] add timers for object scanning and reachability --- .../pointsto/AbstractAnalysisEngine.java | 6 +++ .../reachability/ReachabilityAnalysis.java | 45 +++++++++++-------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java index 9d2edbf78aaa..5d5ccb83b617 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java @@ -54,6 +54,8 @@ public abstract class AbstractAnalysisEngine implements BigBang { private final Boolean extendedAsserts; private final Timer processFeaturesTimer; private final Timer analysisTimer; + protected final Timer checkObjectsTimer; + protected final Timer reachabilityTimer; protected final AnalysisMetaAccess metaAccess; private final HostedProviders providers; protected final HostVM hostVM; @@ -89,6 +91,8 @@ public AbstractAnalysisEngine(OptionValues options, AnalysisUniverse universe, H String imageName = hostVM.getImageName(); this.processFeaturesTimer = new Timer(imageName, "(features)", false); + this.checkObjectsTimer = new Timer(imageName, "(objects)", false); + this.reachabilityTimer = new Timer(imageName, "(reachability)", false); this.analysisTimer = new Timer(imageName, "analysis", true); this.extendedAsserts = PointstoOptions.ExtendedAsserts.getValue(options); @@ -117,6 +121,8 @@ public Timer getProcessFeaturesTimer() { @Override public void printTimers() { + reachabilityTimer.print(); + checkObjectsTimer.print(); processFeaturesTimer.print(); } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index 477fec096bcf..eef58991209d 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -35,6 +35,7 @@ import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.graal.pointsto.meta.HostedProviders; import com.oracle.graal.pointsto.typestate.TypeState; +import com.oracle.graal.pointsto.util.Timer; import jdk.vm.ci.code.BytecodePosition; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; @@ -260,36 +261,44 @@ public boolean finish() throws InterruptedException { universe.setAnalysisDataValid(false); // todo transform into a real 'run until fixpoint' loop for (int i = 0; i < 10; i++) { + runReachability(); + + checkObjectGraph(); + } + universe.setAnalysisDataValid(true); + return true; + } + + private void runReachability() throws InterruptedException { + try (Timer.StopTimer t = reachabilityTimer.start()) { if (!executor.isStarted()) { executor.start(); } executor.complete(); executor.shutdown(); executor.init(timing); - - checkObjectGraph(); } - universe.setAnalysisDataValid(true); - return true; } - private ObjectScanner.ReusableSet scannedObjects = new ObjectScanner.ReusableSet(); + private final ObjectScanner.ReusableSet scannedObjects = new ObjectScanner.ReusableSet(); @SuppressWarnings("try") private void checkObjectGraph() throws InterruptedException { - scannedObjects.reset(); - // scan constants - boolean isParallel = PointstoOptions.ScanObjectsParallel.getValue(options); - ObjectScanner objectScanner = new ReachabilityObjectScanner(this, isParallel ? executor : null, scannedObjects, metaAccess); - checkObjectGraph(objectScanner); - if (isParallel) { - executor.start(); - objectScanner.scanBootImageHeapRoots(null, null); - executor.complete(); - executor.shutdown(); - executor.init(null); - } else { - objectScanner.scanBootImageHeapRoots(null, null); + try (Timer.StopTimer t = checkObjectsTimer.start()) { + scannedObjects.reset(); + // scan constants + boolean isParallel = PointstoOptions.ScanObjectsParallel.getValue(options); + ObjectScanner objectScanner = new ReachabilityObjectScanner(this, isParallel ? executor : null, scannedObjects, metaAccess); + checkObjectGraph(objectScanner); + if (isParallel) { + executor.start(); + objectScanner.scanBootImageHeapRoots(null, null); + executor.complete(); + executor.shutdown(); + executor.init(null); + } else { + objectScanner.scanBootImageHeapRoots(null, null); + } } } From c0a61569282ded65e6a351432082e02e20994930 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Mon, 18 Oct 2021 11:50:38 +0200 Subject: [PATCH 25/65] use a proper fixpoint iteration in ReachabilityAnalysis.finish --- .../graal/reachability/ReachabilityAnalysis.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index eef58991209d..20f0a15b5594 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -259,13 +259,20 @@ private void onMethodInvoked(AnalysisMethod method) { @Override public boolean finish() throws InterruptedException { universe.setAnalysisDataValid(false); - // todo transform into a real 'run until fixpoint' loop - for (int i = 0; i < 10; i++) { + + int numTypes; + do { runReachability(); + assert executor.getPostedOperations() == 0; + numTypes = universe.getTypes().size(); + checkObjectGraph(); - } + + } while (executor.getPostedOperations() != 0 || numTypes != universe.getTypes().size()); + universe.setAnalysisDataValid(true); + return true; } From addcdeeab9fa5240c6fa3b43d40c89bd06b8acdf Mon Sep 17 00:00:00 2001 From: David Kozak Date: Tue, 19 Oct 2021 13:35:45 +0200 Subject: [PATCH 26/65] extra compilation dumps --- .../svm/hosted/NativeImageGenerator.java | 33 ++++++++++++++--- .../oracle/svm/hosted/code/CompileQueue.java | 36 ++++++++++++++++--- 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index 5cd06e3173ee..6c2de2028e2d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -627,6 +627,9 @@ private void doRun(Map entryPoints, compileQueue = HostedConfiguration.instance().createCompileQueue(debug, featureHandler, hUniverse, runtime, DeoptTester.enabled(), bb.getProviders().getSnippetReflection(), compilationExecutor); compileQueue.finish(debug); + System.out.println("Number of parsed methods: " + CompileQueue.parsedMethods.size()); + System.out.println("Number of compiled methods: " + CompileQueue.compiledMethods.size()); + dumpParseTree(compileQueue); /* release memory taken by graphs for the image writing */ hUniverse.getMethods().forEach(HostedMethod::clear); @@ -706,6 +709,7 @@ private void doRun(Map entryPoints, } private static final String DUMP_FOLDER = "/Users/dkozak/tmp/hello-dir/stats/"; + private static final String METHOD_FORMAT = "%H.%n(%P)"; private void dumpAnalysisStats() { AnalysisUniverse universe = getBigbang().getUniverse(); @@ -716,14 +720,13 @@ private void dumpAnalysisStats() { System.out.println("Invoked methods " + invokedMethods.size()); System.out.println("Implementation invoked methods " + implInvokedMethods.size()); - boolean useReachability = NativeImageOptions.UseExperimentalReachabilityAnalysis.getValue(); - String fileName = useReachability ? "reachability_" : "points-to_"; + String prefix = analysisPrefix(); List, String>> pairs = Arrays.asList(Pair.create(reachableTypes, "types"), Pair.create(invokedMethods, "invokedMethods"), Pair.create(implInvokedMethods, "implInvokedMethods")); for (Pair, String> pair : pairs) { - try (FileWriter writer = new FileWriter(DUMP_FOLDER + fileName + pair.getRight())) { + try (FileWriter writer = new FileWriter(DUMP_FOLDER + prefix + pair.getRight())) { for (String line : pair.getLeft()) { writer.write(line); writer.write('\n'); @@ -733,10 +736,10 @@ private void dumpAnalysisStats() { } } - try (FileWriter writer = new FileWriter(DUMP_FOLDER + fileName + "invokeStats")) { + try (FileWriter writer = new FileWriter(DUMP_FOLDER + prefix + "invokeStats")) { List implInvoked = universe.getMethods().stream().filter(AnalysisMethod::isImplementationInvoked).collect(Collectors.toList()); for (AnalysisMethod method : implInvoked) { - writer.write(method.format("%H.%n(%P)")); + writer.write(method.format(METHOD_FORMAT)); writer.write(','); List callees = getCallees(method); writer.write(Integer.toString(callees.size())); @@ -747,6 +750,26 @@ private void dumpAnalysisStats() { } } + private String analysisPrefix() { + return NativeImageOptions.UseExperimentalReachabilityAnalysis.getValue() ? "reachability_" : "points-to_"; + } + + private void dumpParseTree(CompileQueue compileQueue) { + String prefix = analysisPrefix(); + List>> entries = CompileQueue.parseTree.entrySet().stream().sorted(Comparator.comparing(entry -> entry.getKey().format(METHOD_FORMAT))) + .collect(Collectors.toList()); + try (FileWriter writer = new FileWriter(DUMP_FOLDER + prefix + "parse_tree")) { + for (Map.Entry> entry : entries) { + writer.write(entry.getKey().format(METHOD_FORMAT)); + writer.write(','); + writer.write(Integer.toString(entry.getValue().size())); + writer.write('\n'); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + private List getCallees(AnalysisMethod method) { if (bb instanceof NativeImageReachabilityAnalysis) { return getCalleesR(((NativeImageReachabilityAnalysis) bb), method); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java index bd591129a554..e19bc34f1dee 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java @@ -29,6 +29,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.IdentityHashMap; @@ -36,10 +37,12 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Objects; +import java.util.Set; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ForkJoinPool; +import java.util.stream.Collectors; import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.api.replacements.Fold; @@ -456,7 +459,7 @@ protected PhaseSuite afterParseCanonicalization() { phaseSuite.appendPhase(new DeadStoreRemovalPhase()); phaseSuite.appendPhase(new DevirtualizeCallsPhase()); phaseSuite.appendPhase(CanonicalizerPhase.create()); - phaseSuite.appendPhase(new StrengthenStampsPhase()); +// phaseSuite.appendPhase(new StrengthenStampsPhase()); phaseSuite.appendPhase(CanonicalizerPhase.create()); phaseSuite.appendPhase(new OptimizeExceptionPathsPhase()); if (ImageBuildStatistics.Options.CollectImageBuildStatistics.getValue(universe.hostVM().options())) { @@ -553,14 +556,19 @@ protected void parseAll() throws InterruptedException { * parsed methods. */ private void parseAheadOfTimeCompiledMethods() { - universe.getMethods().stream() + List entryPoints = universe.getMethods().stream() .filter(method -> method.isEntryPoint() || CompilationInfoSupport.singleton().isForcedCompilation(method)) - .forEach(method -> ensureParsed(method, null, new EntryPointReason())); + .collect(Collectors.toList()); + System.out.println("Entry points: " + entryPoints.size()); + entryPoints.forEach(method -> ensureParsed(method, null, new EntryPointReason())); SubstrateForeignCallsProvider foreignCallsProvider = (SubstrateForeignCallsProvider) runtimeConfig.getProviders().getForeignCalls(); - foreignCallsProvider.getForeignCalls().values().stream() + List foreignCallEntryPoints = foreignCallsProvider.getForeignCalls().values().stream() .map(linkage -> (HostedMethod) linkage.getDescriptor().findMethod(runtimeConfig.getProviders().getMetaAccess())) .filter(method -> method.wrapped.isRootMethod()) + .collect(Collectors.toList()); + System.out.println("Foreign call entry points: " + foreignCallEntryPoints.size()); + foreignCallEntryPoints .forEach(method -> ensureParsed(method, null, new EntryPointReason())); } @@ -1018,6 +1026,8 @@ private void transplantVirtualObjectState(VirtualObjectNode virtualObject, List< private final boolean parseOnce = SubstrateOptions.parseOnce(); + public static final Set parsedMethods = ConcurrentHashMap.newKeySet(); + @SuppressWarnings("try") private void defaultParseFunction(DebugContext debug, HostedMethod method, CompileReason reason, RuntimeConfiguration config) { if (method.getAnnotation(NodeIntrinsic.class) != null) { @@ -1092,6 +1102,8 @@ private void defaultParseFunction(DebugContext debug, HostedMethod method, Compi } } + parsedMethods.add(method); + } catch (Throwable ex) { GraalError error = ex instanceof GraalError ? (GraalError) ex : new GraalError(ex); error.addContext("method: " + method.format("%r %H.%n(%p)")); @@ -1103,9 +1115,18 @@ private void defaultParseFunction(DebugContext debug, HostedMethod method, Compi } } + public static final Map> parseTree = new ConcurrentHashMap<>(); + + private static List getEntry(HostedMethod method) { + return parseTree.computeIfAbsent(method, key -> Collections.synchronizedList(new ArrayList<>())); + } + private void ensureParsed(HostedMethod method, CompileReason reason, CallTargetNode targetNode, HostedMethod invokeTarget, boolean isIndirect) { if (isIndirect) { - for (HostedMethod invokeImplementation : invokeTarget.getImplementations()) { + HostedMethod[] implementations = invokeTarget.getImplementations(); + List targets = getEntry(method); + Collections.addAll(targets, implementations); + for (HostedMethod invokeImplementation : implementations) { handleSpecialization(method, targetNode, invokeTarget, invokeImplementation); ensureParsed(invokeImplementation, method, new VirtualCallReason(method, invokeImplementation, reason)); } @@ -1121,6 +1142,7 @@ private void ensureParsed(HostedMethod method, CompileReason reason, CallTargetN * implementation invoked status. */ if (invokeTarget.wrapped.isSimplyImplementationInvoked()) { + getEntry(method).add(invokeTarget); handleSpecialization(method, targetNode, invokeTarget, invokeTarget); ensureParsed(invokeTarget, method, new DirectCallReason(method, reason)); } @@ -1299,6 +1321,8 @@ protected CompilationResult doCompile(DebugContext debug, final HostedMethod met return fun.compile(debug, method, compilationIdentifier, reason, runtimeConfig); } + public static final Set compiledMethods = ConcurrentHashMap.newKeySet(); + @SuppressWarnings("try") private CompilationResult defaultCompileFunction(DebugContext debug, HostedMethod method, CompilationIdentifier compilationIdentifier, CompileReason reason, RuntimeConfiguration config) { if (NativeImageOptions.PrintAOTCompilation.getValue()) { @@ -1352,6 +1376,8 @@ private CompilationResult defaultCompileFunction(DebugContext debug, HostedMetho result.setTargetCode(Arrays.copyOf(result.getTargetCode(), result.getTargetCodeSize()), result.getTargetCodeSize()); } + compiledMethods.add(method); + return result; } } catch (Throwable ex) { From 7a002cfc5eb77b4f2d9b87629c673f78b23138f9 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Tue, 19 Oct 2021 14:07:36 +0200 Subject: [PATCH 27/65] add foreign calls to method summaries --- .../oracle/graal/reachability/MethodSummary.java | 15 ++++++++++++--- .../graal/reachability/ReachabilityAnalysis.java | 7 +++++++ .../SimpleInMemoryMethodSummaryProvider.java | 15 ++++++++++++++- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java index 29db59c95fdc..132053c42fd4 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java @@ -28,12 +28,14 @@ import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.graal.pointsto.meta.AnalysisType; import jdk.vm.ci.meta.JavaConstant; +import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.core.common.spi.ForeignCallSignature; import java.util.Arrays; public class MethodSummary { public static final MethodSummary EMPTY = new MethodSummary(new AnalysisMethod[0], new AnalysisMethod[0], new AnalysisType[0], new AnalysisType[0], new AnalysisField[0], new AnalysisField[0], - new JavaConstant[0]); + new JavaConstant[0], new ForeignCallDescriptor[0], new ForeignCallSignature[0]); public final AnalysisMethod[] invokedMethods; public final AnalysisMethod[] implementationInvokedMethods; @@ -42,10 +44,14 @@ public class MethodSummary { public final AnalysisField[] readFields; public final AnalysisField[] writtenFields; public final JavaConstant[] embeddedConstants; + public final ForeignCallDescriptor[] foreignCallDescriptors; + public final ForeignCallSignature[] foreignCallSignatures; public MethodSummary(AnalysisMethod[] invokedMethods, AnalysisMethod[] implementationInvokedMethods, AnalysisType[] accessedTypes, AnalysisType[] instantiatedTypes, AnalysisField[] readFields, AnalysisField[] writtenFields, - JavaConstant[] embeddedConstants) { + JavaConstant[] embeddedConstants, + ForeignCallDescriptor[] foreignCallDescriptors, + ForeignCallSignature[] foreignCallSignatures) { this.invokedMethods = invokedMethods; this.implementationInvokedMethods = implementationInvokedMethods; this.accessedTypes = accessedTypes; @@ -53,6 +59,8 @@ public MethodSummary(AnalysisMethod[] invokedMethods, AnalysisMethod[] implement this.readFields = readFields; this.writtenFields = writtenFields; this.embeddedConstants = embeddedConstants; + this.foreignCallDescriptors = foreignCallDescriptors; + this.foreignCallSignatures = foreignCallSignatures; } @Override @@ -69,6 +77,7 @@ public String toString() { } public MethodSummary withoutMethods() { - return new MethodSummary(new AnalysisMethod[0], new AnalysisMethod[0], accessedTypes, instantiatedTypes, readFields, writtenFields, embeddedConstants); + return new MethodSummary(new AnalysisMethod[0], new AnalysisMethod[0], accessedTypes, instantiatedTypes, readFields, writtenFields, embeddedConstants, foreignCallDescriptors, + foreignCallSignatures); } } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index 20f0a15b5594..d9783f13a9eb 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -41,6 +41,7 @@ import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.core.common.spi.ForeignCallSignature; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.FrameState; @@ -181,6 +182,12 @@ private void processSummary(AnalysisMethod method, MethodSummary summary) { } } } + for (ForeignCallDescriptor descriptor : summary.foreignCallDescriptors) { + registerForeignCall(descriptor); + } + for (ForeignCallSignature signature : summary.foreignCallSignatures) { + registerForeignCall(getProviders().getForeignCalls().getDescriptor(signature)); + } } @Override diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java index c020427bcba9..05191b5c03f2 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java @@ -37,12 +37,15 @@ import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; +import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.core.common.spi.ForeignCallSignature; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.CallTargetNode; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.extended.ForeignCall; import org.graalvm.compiler.nodes.java.AccessFieldNode; import org.graalvm.compiler.nodes.java.InstanceOfNode; import org.graalvm.compiler.nodes.java.LoadFieldNode; @@ -50,7 +53,9 @@ import org.graalvm.compiler.nodes.java.NewInstanceNode; import org.graalvm.compiler.nodes.java.NewMultiArrayNode; import org.graalvm.compiler.nodes.java.StoreFieldNode; +import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode; import org.graalvm.compiler.replacements.nodes.MacroInvokable; +import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode; import java.util.ArrayList; import java.util.List; @@ -113,6 +118,8 @@ protected class Instance { public final List invokedMethods = new ArrayList<>(); public final List implementationInvokedMethods = new ArrayList<>(); public final List embeddedConstants = new ArrayList<>(); + public final List foreignCallDescriptors = new ArrayList<>(); + public final List foreignCallSignatures = new ArrayList<>(); private MethodSummary createSummaryFromGraph(StructuredGraph graph) { @@ -182,13 +189,19 @@ private MethodSummary createSummaryFromGraph(StructuredGraph graph) { } else { invokedMethods.add(targetMethod); } + } else if (n instanceof ForeignCall) { + foreignCallDescriptors.add(((ForeignCall) n).getDescriptor()); + } else if (n instanceof UnaryMathIntrinsicNode) { + foreignCallSignatures.add(((UnaryMathIntrinsicNode) n).getOperation().foreignCallSignature); + } else if (n instanceof BinaryMathIntrinsicNode) { + foreignCallSignatures.add(((BinaryMathIntrinsicNode) n).getOperation().foreignCallSignature); } delegateNodeProcessing(this, n); } return new MethodSummary(invokedMethods.toArray(new AnalysisMethod[0]), implementationInvokedMethods.toArray(new AnalysisMethod[0]), accessedTypes.toArray(new AnalysisType[0]), instantiatedTypes.toArray(new AnalysisType[0]), readFields.toArray(new AnalysisField[0]), writtenFields.toArray(new AnalysisField[0]), - embeddedConstants.toArray(new JavaConstant[0])); + embeddedConstants.toArray(new JavaConstant[0]), foreignCallDescriptors.toArray(new ForeignCallDescriptor[0]), foreignCallSignatures.toArray(new ForeignCallSignature[0])); } } } From 5c0c56514ebc7e243f89ac1b45ba6ccf3ff69a8f Mon Sep 17 00:00:00 2001 From: David Kozak Date: Tue, 19 Oct 2021 17:52:03 +0200 Subject: [PATCH 28/65] add timer for getting method summaries --- .../reachability/ReachabilityAnalysis.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index d9783f13a9eb..a663e9dbd1e6 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -63,12 +63,14 @@ public abstract class ReachabilityAnalysis extends AbstractReachabilityAnalysis private final MethodSummaryProvider methodSummaryProvider; private final AnalysisType objectType; + private final Timer summaryTimer; public ReachabilityAnalysis(OptionValues options, AnalysisUniverse universe, HostedProviders providers, HostVM hostVM, ForkJoinPool executorService, Runnable heartbeatCallback, UnsupportedFeatures unsupportedFeatures, MethodSummaryProvider methodSummaryProvider) { super(options, universe, providers, hostVM, executorService, heartbeatCallback, unsupportedFeatures); this.methodSummaryProvider = methodSummaryProvider; this.objectType = metaAccess.lookupJavaType(Object.class); + this.summaryTimer = new Timer(hostVM.getImageName(), "((summaries))", false); } @Override @@ -137,7 +139,10 @@ public void markMethodImplementationInvoked(AnalysisMethod method, Object reason private void onMethodImplementationInvoked(AnalysisMethod method) { try { - MethodSummary summary = methodSummaryProvider.getSummary(this, method); + MethodSummary summary; + try (Timer.StopTimer t = summaryTimer.start()) { + summary = methodSummaryProvider.getSummary(this, method); + } processSummary(method, summary); summaries.put(method, summary); } catch (Throwable ex) { @@ -229,7 +234,7 @@ public void markTypeInstantiated(AnalysisType type) { } AnalysisMethod implementationInvokedMethod = type.resolveConcreteMethod(method, current); if (implementationInvokedMethod == null) { - System.out.println("onMethodInvoked: method " + method + " on type " + current + " is null"); +// System.out.println("onMethodInvoked: method " + method + " on type " + current + " is null"); continue; } markMethodImplementationInvoked(implementationInvokedMethod, type); // todo better @@ -256,7 +261,7 @@ private void onMethodInvoked(AnalysisMethod method) { for (AnalysisType subtype : instantiatedSubtypes) { AnalysisMethod resolvedMethod = subtype.resolveConcreteMethod(method, clazz); if (resolvedMethod == null) { - System.out.println("onMethodInvoked: method " + method + " on type " + subtype + " is null"); +// System.out.println("onMethodInvoked: method " + method + " on type " + subtype + " is null"); continue; } markMethodImplementationInvoked(resolvedMethod, method); // todo better reason @@ -340,7 +345,10 @@ public TypeState getAllSynchronizedTypeState() { } public void processGraph(StructuredGraph graph) { - MethodSummary summary = methodSummaryProvider.getSummary(this, graph); + MethodSummary summary; + try (Timer.StopTimer t = summaryTimer.start()) { + summary = methodSummaryProvider.getSummary(this, graph); + } AnalysisMethod method = analysisMethod(graph.method()); method.registerAsInvoked(null); method.registerAsImplementationInvoked(null); @@ -351,7 +359,6 @@ public void processGraph(StructuredGraph graph) { private void registerForeignCalls(StructuredGraph graph) { for (Node n : graph.getNodes()) { - // todo handle foreign calls even in the summary provider? if (n instanceof ForeignCall) { ForeignCall node = (ForeignCall) n; registerForeignCall(node.getDescriptor()); @@ -379,4 +386,10 @@ private void registerForeignCall(ForeignCallDescriptor descriptor) { private AnalysisMethod analysisMethod(ResolvedJavaMethod method) { return method instanceof AnalysisMethod ? ((AnalysisMethod) method) : universe.lookup(method); } + + @Override + public void printTimers() { + summaryTimer.print(); + super.printTimers(); + } } From 2a6cd03cf0f9d0476c9d71e14a20ee1df1b0fb11 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Tue, 19 Oct 2021 18:57:47 +0200 Subject: [PATCH 29/65] fixes after rebase --- substratevm/mx.substratevm/suite.py | 15 ++++++ .../com/oracle/graal/pointsto/BigBang.java | 10 ++++ .../reachability/ReachabilityAnalysis.java | 48 ++++++++++++++++++- .../ReachabilityObjectScanner.java | 31 ++++++++---- .../NativeImageReachabilityAnalysis.java | 8 ++-- 5 files changed, 98 insertions(+), 14 deletions(-) diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 560c8ada731d..bac3cab3b4d8 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -408,6 +408,21 @@ "workingSets": "SVM", }, + + "com.oracle.graal.reachability": { + "subDir": "src", + "sourceDirs": ["src"], + "dependencies": [ + "com.oracle.graal.pointsto", + ], + "checkstyle": "com.oracle.graal.pointsto", + "javaCompliance": "11+", + "annotationProcessors": [ + "compiler:GRAAL_PROCESSOR", + ], + "workingSets": "SVM", + }, + "com.oracle.svm.hosted": { "subDir": "src", "sourceDirs": ["src"], diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java index 8d40f8598968..32bbb43ac550 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java @@ -45,6 +45,16 @@ import com.oracle.graal.pointsto.util.Timer; import jdk.vm.ci.meta.ConstantReflectionProvider; +import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.graph.NodeSourcePosition; +import org.graalvm.compiler.options.OptionValues; + +import java.io.PrintWriter; +import java.util.List; +import java.util.function.Function; + /** * Central static analysis interface that groups together the functionality of reachability analysis diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index a663e9dbd1e6..bac3516922bc 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -35,6 +35,7 @@ import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.graal.pointsto.meta.HostedProviders; import com.oracle.graal.pointsto.typestate.TypeState; +import com.oracle.graal.pointsto.util.AnalysisError; import com.oracle.graal.pointsto.util.Timer; import jdk.vm.ci.code.BytecodePosition; import jdk.vm.ci.meta.JavaConstant; @@ -42,6 +43,7 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallSignature; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.FrameState; @@ -56,6 +58,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ForkJoinPool; +import java.util.function.Function; import static jdk.vm.ci.common.JVMCIError.shouldNotReachHere; @@ -288,6 +291,48 @@ public boolean finish() throws InterruptedException { return true; } + @Override + public void runAnalysis(DebugContext debugContext, Function analysisEndCondition) throws InterruptedException { + // todo this is ugly copy paste from points-to + int numIterations = 0; + while (true) { + try (Indent indent2 = debugContext.logAndIndent("new analysis iteration")) { + /* + * Do the analysis (which itself is done in a similar iterative process) + */ + boolean analysisChanged = finish(); + + numIterations++; + if (numIterations > 1000) { + /* + * Usually there are < 10 iterations. If we have so many iterations, we probably + * have an endless loop (but at least we have a performance problem because we + * re-start the analysis so often). + */ + throw AnalysisError.shouldNotReachHere(String.format("Static analysis did not reach a fix point after %d iterations because a Feature keeps requesting new analysis iterations. " + + "The analysis itself %s find a change in type states in the last iteration.", + numIterations, analysisChanged ? "DID" : "DID NOT")); + } + + /* + * Allow features to change the universe. + */ + try (Timer.StopTimer t2 = getProcessFeaturesTimer().start()) { + int numTypes = universe.getTypes().size(); + int numMethods = universe.getMethods().size(); + int numFields = universe.getFields().size(); + if (analysisEndCondition.apply(universe)) { + if (numTypes != universe.getTypes().size() || numMethods != universe.getMethods().size() || numFields != universe.getFields().size()) { + throw AnalysisError.shouldNotReachHere( + "When a feature makes more types, methods, or fields reachable, it must require another analysis iteration via DuringAnalysisAccess.requireAnalysisIteration()"); + } + return; + } + } + } + } + } + private void runReachability() throws InterruptedException { try (Timer.StopTimer t = reachabilityTimer.start()) { if (!executor.isStarted()) { @@ -307,7 +352,8 @@ private void checkObjectGraph() throws InterruptedException { scannedObjects.reset(); // scan constants boolean isParallel = PointstoOptions.ScanObjectsParallel.getValue(options); - ObjectScanner objectScanner = new ReachabilityObjectScanner(this, isParallel ? executor : null, scannedObjects, metaAccess); + ObjectScanner objectScanner = new ObjectScanner(this, isParallel ? executor : null, scannedObjects, new ReachabilityObjectScanner(this, metaAccess)) { + }; checkObjectGraph(objectScanner); if (isParallel) { executor.start(); diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityObjectScanner.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityObjectScanner.java index 440779fbbc27..a660d2cbb08c 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityObjectScanner.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityObjectScanner.java @@ -2,19 +2,20 @@ import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.ObjectScanner; +import com.oracle.graal.pointsto.ObjectScanningObserver; import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; import com.oracle.graal.pointsto.meta.AnalysisType; -import com.oracle.graal.pointsto.util.CompletionExecutor; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; -public class ReachabilityObjectScanner extends ObjectScanner { +public class ReachabilityObjectScanner implements ObjectScanningObserver { + private final ReachabilityAnalysis bb; private final AnalysisMetaAccess access; - public ReachabilityObjectScanner(BigBang bb, CompletionExecutor executor, ReusableSet scannedObjects, AnalysisMetaAccess access) { - super(bb, executor, scannedObjects); + public ReachabilityObjectScanner(BigBang bb, AnalysisMetaAccess access) { + this.bb = ((ReachabilityAnalysis) bb); this.access = access; } @@ -27,16 +28,17 @@ public void forRelocatedPointerFieldValue(JavaConstant receiver, AnalysisField f field.registerAsAccessed(); if (fieldValue.isNonNull() && fieldValue.getJavaKind() == JavaKind.Object) { // todo mark as instantiated -// getAnalysis().markTypeInstantiated(constantType(bb, fieldValue)); +// getAnalysis().markTypeInstantiated(constantType(bb, fieldValue)); } } @Override public void forNullFieldValue(JavaConstant receiver, AnalysisField field) { - if (receiver != null) + if (receiver != null) { getAnalysis().markTypeReachable(constantType(bb, receiver)); + } getAnalysis().markTypeReachable(field.getType()); -// System.out.println("Scanning field " + field); +// System.out.println("Scanning field " + field); } @Override @@ -44,7 +46,7 @@ public void forNonNullFieldValue(JavaConstant receiver, AnalysisField field, Jav if (receiver != null) getAnalysis().markTypeReachable(constantType(bb, receiver)); getAnalysis().markTypeReachable(field.getType()); -// System.out.println("Scanning field " + field); +// System.out.println("Scanning field " + field); } @Override @@ -59,10 +61,19 @@ public void forNonNullArrayElement(JavaConstant array, AnalysisType arrayType, J } @Override - protected void forScannedConstant(JavaConstant scannedValue, ScanReason reason) { + public void forScannedConstant(JavaConstant scannedValue, ObjectScanner.ScanReason reason) { AnalysisType type = constantType(bb, scannedValue); -// System.out.println("Scanning constant of type " + type); +// System.out.println("Scanning constant of type " + type); getAnalysis().markTypeInstantiated(type); type.registerAsInHeap(); } + + private AnalysisType constantType(BigBang bb, JavaConstant constant) { + return access.lookupJavaType(constantAsObject(bb, constant).getClass()); + } + + public Object constantAsObject(BigBang bb, JavaConstant constant) { + return bb.getSnippetReflectionProvider().asObject(Object.class, constant); + } + } \ No newline at end of file diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java index 4dd41301c608..6eaac229f081 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java @@ -134,6 +134,8 @@ public void checkUserLimitations() { // todo } + // todo remove ugly copy paste from this class + public void checkType(AnalysisType type) { assert type.isReachable(); DynamicHub hub = getHostVM().dynamicHub(type); @@ -237,7 +239,7 @@ static class GenericInterfacesEncodingKey { @Override public boolean equals(Object obj) { - return obj instanceof NativeImagePointsToAnalysis.GenericInterfacesEncodingKey && Arrays.equals(interfaces, ((NativeImagePointsToAnalysis.GenericInterfacesEncodingKey) obj).interfaces); + return obj instanceof GenericInterfacesEncodingKey && Arrays.equals(interfaces, ((GenericInterfacesEncodingKey) obj).interfaces); } @Override @@ -297,8 +299,8 @@ static class AnnotatedInterfacesEncodingKey { @Override public boolean equals(Object obj) { - return obj instanceof NativeImagePointsToAnalysis.AnnotatedInterfacesEncodingKey && - shallowEquals(interfaces, ((NativeImagePointsToAnalysis.AnnotatedInterfacesEncodingKey) obj).interfaces); + return obj instanceof AnnotatedInterfacesEncodingKey && + shallowEquals(interfaces, ((AnnotatedInterfacesEncodingKey) obj).interfaces); } @Override From 7b71240cefe0838e63e387f80c1a810c7b17e6c8 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Tue, 19 Oct 2021 19:04:34 +0200 Subject: [PATCH 30/65] switch the default to reachability to run the gates --- .../src/com/oracle/svm/hosted/NativeImageOptions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java index 5a37e87044d4..beef95d881f8 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java @@ -60,7 +60,7 @@ public class NativeImageOptions { public static final HostedOptionKey NativeArchitecture = new HostedOptionKey<>(false); @Option(help = "Print information about classes, methods, and fields that are present in the native image")// - public static final HostedOptionKey UseExperimentalReachabilityAnalysis = new HostedOptionKey<>(false); + public static final HostedOptionKey UseExperimentalReachabilityAnalysis = new HostedOptionKey<>(true); @Option(help = "Print information about classes, methods, and fields that are present in the native image")// public static final HostedOptionKey PrintUniverse = new HostedOptionKey<>(false); From 6dba8b566338ccdc9c2dd61fcfcca1f97b072dc1 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Wed, 20 Oct 2021 15:16:16 +0200 Subject: [PATCH 31/65] resolve style issues --- substratevm/mx.substratevm/suite.py | 1 - .../reachability/ReachabilityAnalysis.java | 5 ++ .../ReachabilityObjectScanner.java | 48 +++++++++++++------ 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index bac3cab3b4d8..183675027140 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -429,7 +429,6 @@ "dependencies": [ "com.oracle.objectfile", "com.oracle.svm.core", - "com.oracle.graal.pointsto", "com.oracle.graal.reachability" ], "requires" : [ diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index bac3516922bc..ed952413e5a2 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -76,6 +76,7 @@ public ReachabilityAnalysis(OptionValues options, AnalysisUniverse universe, Hos this.summaryTimer = new Timer(hostVM.getImageName(), "((summaries))", false); } + @SuppressWarnings("try") @Override public AnalysisType addRootClass(AnalysisType type, boolean addFields, boolean addArrayClass) { try (Indent indent = debug.logAndIndent("add root class %s", type.getName())) { @@ -97,6 +98,7 @@ public AnalysisType addRootClass(AnalysisType type, boolean addFields, boolean a return type; } + @SuppressWarnings("try") @Override public AnalysisType addRootField(Class clazz, String fieldName) { AnalysisType type = addRootClass(clazz, false, false); @@ -140,6 +142,7 @@ public void markMethodImplementationInvoked(AnalysisMethod method, Object reason public final Map summaries = new ConcurrentHashMap<>(); + @SuppressWarnings("try") private void onMethodImplementationInvoked(AnalysisMethod method) { try { MethodSummary summary; @@ -291,6 +294,7 @@ public boolean finish() throws InterruptedException { return true; } + @SuppressWarnings("try") @Override public void runAnalysis(DebugContext debugContext, Function analysisEndCondition) throws InterruptedException { // todo this is ugly copy paste from points-to @@ -390,6 +394,7 @@ public TypeState getAllSynchronizedTypeState() { return objectType.getTypeFlow(this, true).getState(); } + @SuppressWarnings("try") public void processGraph(StructuredGraph graph) { MethodSummary summary; try (Timer.StopTimer t = summaryTimer.start()) { diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityObjectScanner.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityObjectScanner.java index a660d2cbb08c..4e392e49b9b2 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityObjectScanner.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityObjectScanner.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ package com.oracle.graal.reachability; import com.oracle.graal.pointsto.BigBang; @@ -19,52 +43,48 @@ public ReachabilityObjectScanner(BigBang bb, AnalysisMetaAccess access) { this.access = access; } - ReachabilityAnalysis getAnalysis() { - return ((ReachabilityAnalysis) bb); - } - @Override public void forRelocatedPointerFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) { field.registerAsAccessed(); if (fieldValue.isNonNull() && fieldValue.getJavaKind() == JavaKind.Object) { // todo mark as instantiated -// getAnalysis().markTypeInstantiated(constantType(bb, fieldValue)); +// bb.markTypeInstantiated(constantType(bb, fieldValue)); } } @Override public void forNullFieldValue(JavaConstant receiver, AnalysisField field) { if (receiver != null) { - getAnalysis().markTypeReachable(constantType(bb, receiver)); + bb.markTypeReachable(constantType(bb, receiver)); } - getAnalysis().markTypeReachable(field.getType()); + bb.markTypeReachable(field.getType()); // System.out.println("Scanning field " + field); } @Override public void forNonNullFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) { if (receiver != null) - getAnalysis().markTypeReachable(constantType(bb, receiver)); - getAnalysis().markTypeReachable(field.getType()); + bb.markTypeReachable(constantType(bb, receiver)); + bb.markTypeReachable(field.getType()); // System.out.println("Scanning field " + field); } @Override public void forNullArrayElement(JavaConstant array, AnalysisType arrayType, int elementIndex) { - getAnalysis().markTypeReachable(arrayType); + bb.markTypeReachable(arrayType); } @Override public void forNonNullArrayElement(JavaConstant array, AnalysisType arrayType, JavaConstant elementConstant, AnalysisType elementType, int elementIndex) { - getAnalysis().markTypeReachable(arrayType); - getAnalysis().markTypeInstantiated(elementType); + bb.markTypeReachable(arrayType); + bb.markTypeInstantiated(elementType); } @Override public void forScannedConstant(JavaConstant scannedValue, ObjectScanner.ScanReason reason) { AnalysisType type = constantType(bb, scannedValue); // System.out.println("Scanning constant of type " + type); - getAnalysis().markTypeInstantiated(type); + bb.markTypeInstantiated(type); type.registerAsInHeap(); } @@ -76,4 +96,4 @@ public Object constantAsObject(BigBang bb, JavaConstant constant) { return bb.getSnippetReflectionProvider().asObject(Object.class, constant); } -} \ No newline at end of file +} From 99d14b4352a78f7ccbd372ce7b0cc1665a2e2fe8 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Fri, 22 Oct 2021 17:10:18 +0200 Subject: [PATCH 32/65] fix various style issues --- .../results/StaticAnalysisResultsBuilder.java | 34 +++++++++---------- .../pointsto/results/StrengthenGraphs.java | 24 +++++++------ .../ReachabilityObjectScanner.java | 15 ++++---- .../SimpleInMemoryMethodSummaryProvider.java | 1 + .../svm/hosted/HostedConfiguration.java | 3 -- .../svm/hosted/NativeImageGenerator.java | 23 ++++++------- .../oracle/svm/hosted/analysis/Inflation.java | 1 + .../NativeImageReachabilityAnalysis.java | 4 +-- .../oracle/svm/hosted/code/CompileQueue.java | 2 +- .../hosted/phases/StrengthenStampsPhase.java | 8 ++--- 10 files changed, 59 insertions(+), 56 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StaticAnalysisResultsBuilder.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StaticAnalysisResultsBuilder.java index 6777ecd49887..3fdd48be2c14 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StaticAnalysisResultsBuilder.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StaticAnalysisResultsBuilder.java @@ -58,13 +58,13 @@ public StaticAnalysisResultsBuilder(PointsToAnalysis bb, Universe converter) { super(bb, converter); } - PointsToAnalysis getAnalysis() { + private PointsToAnalysis getAnalysis() { return ((PointsToAnalysis) bb); } @Override public StaticAnalysisResults makeOrApplyResults(AnalysisMethod method) { - PointsToAnalysis bb = getAnalysis(); + PointsToAnalysis pointsToAnalysis = getAnalysis(); MethodTypeFlow methodFlow = PointsToAnalysis.assertPointsToAnalysisMethod(method).getTypeFlow(); MethodFlowsGraph originalFlows = methodFlow.getOriginalMethodFlows(); @@ -80,12 +80,12 @@ public StaticAnalysisResults makeOrApplyResults(AnalysisMethod method) { */ continue; } - if (methodFlow.isSaturated(bb, parameter)) { + if (methodFlow.isSaturated(pointsToAnalysis, parameter)) { /* The parameter type flow is saturated, it's type state doesn't matter. */ continue; } - TypeState paramTypeState = methodFlow.foldTypeFlow(bb, parameter); + TypeState paramTypeState = methodFlow.foldTypeFlow(pointsToAnalysis, parameter); JavaTypeProfile paramProfile = makeTypeProfile(paramTypeState); if (paramProfile != null) { ensureSize(paramProfiles, i); @@ -97,7 +97,7 @@ public StaticAnalysisResults makeOrApplyResults(AnalysisMethod method) { parameterTypeProfiles = paramProfiles.toArray(new JavaTypeProfile[paramProfiles.size()]); } - JavaTypeProfile resultTypeProfile = makeTypeProfile(methodFlow.foldTypeFlow(bb, originalFlows.getResult())); + JavaTypeProfile resultTypeProfile = makeTypeProfile(methodFlow.foldTypeFlow(pointsToAnalysis, originalFlows.getResult())); ArrayList entries = new ArrayList<>(method.getCodeSize()); @@ -106,7 +106,7 @@ public StaticAnalysisResults makeOrApplyResults(AnalysisMethod method) { int bci = (int) entry.getKey(); InstanceOfTypeFlow originalInstanceOf = entry.getValue(); - if (methodFlow.isSaturated(bb, originalInstanceOf)) { + if (methodFlow.isSaturated(pointsToAnalysis, originalInstanceOf)) { /* * If the instance flow is saturated its exact type state doesn't matter. This * instanceof cannot be optimized. @@ -115,8 +115,8 @@ public StaticAnalysisResults makeOrApplyResults(AnalysisMethod method) { } /* Fold the instanceof flows. */ - TypeState instanceOfTypeState = methodFlow.foldTypeFlow(bb, originalInstanceOf); - originalInstanceOf.setState(bb, instanceOfTypeState); + TypeState instanceOfTypeState = methodFlow.foldTypeFlow(pointsToAnalysis, originalInstanceOf); + originalInstanceOf.setState(pointsToAnalysis, instanceOfTypeState); JavaTypeProfile typeProfile = makeTypeProfile(instanceOfTypeState); if (typeProfile != null) { @@ -134,17 +134,17 @@ public StaticAnalysisResults makeOrApplyResults(AnalysisMethod method) { TypeState invokeTypeState = null; /* If the receiver flow is saturated its exact type state doesn't matter. */ - if (originalInvoke.getTargetMethod().hasReceiver() && !methodFlow.isSaturated(bb, originalInvoke.getReceiver())) { - invokeTypeState = methodFlow.foldTypeFlow(bb, originalInvoke.getReceiver()); - originalInvoke.setState(bb, invokeTypeState); + if (originalInvoke.getTargetMethod().hasReceiver() && !methodFlow.isSaturated(pointsToAnalysis, originalInvoke.getReceiver())) { + invokeTypeState = methodFlow.foldTypeFlow(pointsToAnalysis, originalInvoke.getReceiver()); + originalInvoke.setState(pointsToAnalysis, invokeTypeState); } TypeFlow originalReturn = originalInvoke.getActualReturn(); TypeState returnTypeState = null; /* If the return flow is saturated its exact type state doesn't matter. */ - if (originalReturn != null && !methodFlow.isSaturated(bb, originalReturn)) { - returnTypeState = methodFlow.foldTypeFlow(bb, originalReturn); - originalReturn.setState(bb, returnTypeState); + if (originalReturn != null && !methodFlow.isSaturated(pointsToAnalysis, originalReturn)) { + returnTypeState = methodFlow.foldTypeFlow(pointsToAnalysis, originalReturn); + originalReturn.setState(pointsToAnalysis, returnTypeState); } JavaTypeProfile typeProfile = makeTypeProfile(invokeTypeState); @@ -159,7 +159,7 @@ public StaticAnalysisResults makeOrApplyResults(AnalysisMethod method) { } } - if (PointstoOptions.PrintSynchronizedAnalysis.getValue(bb.getOptions())) { + if (PointstoOptions.PrintSynchronizedAnalysis.getValue(pointsToAnalysis.getOptions())) { originalFlows.getMiscFlows().stream() .filter(flow -> flow instanceof MonitorEnterTypeFlow) .map(flow -> (MonitorEnterTypeFlow) flow) @@ -167,8 +167,8 @@ public StaticAnalysisResults makeOrApplyResults(AnalysisMethod method) { .sorted(Comparator.comparingInt(m2 -> m2.getState().typesCount())) .forEach(monitorEnter -> { TypeState monitorEntryState = monitorEnter.getState(); - String typesString = TypeStateUtils.closeToAllInstantiated(bb, monitorEntryState) ? "close to all instantiated" - : StreamSupport.stream(monitorEntryState.types(bb).spliterator(), false).map(AnalysisType::getName).collect(Collectors.joining(", ")); + String typesString = TypeStateUtils.closeToAllInstantiated(pointsToAnalysis, monitorEntryState) ? "close to all instantiated" + : StreamSupport.stream(monitorEntryState.types(pointsToAnalysis).spliterator(), false).map(AnalysisType::getName).collect(Collectors.joining(", ")); StringBuilder strb = new StringBuilder(); strb.append("Location: "); String methodName = method.format("%h.%n(%p)"); diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StrengthenGraphs.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StrengthenGraphs.java index 0d44fbc2839c..3b49641fa5a5 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StrengthenGraphs.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StrengthenGraphs.java @@ -113,6 +113,10 @@ public StrengthenGraphs(PointsToAnalysis bb, Universe converter) { super(bb, converter); } + private PointsToAnalysis getAnalysis() { + return ((PointsToAnalysis) bb); + } + @Override @SuppressWarnings("try") public StaticAnalysisResults makeOrApplyResults(AnalysisMethod method) { @@ -284,7 +288,7 @@ public void simplify(Node n, SimplifierTool tool) { } private void handleInvoke(Invoke invoke, SimplifierTool tool) { - PointsToAnalysis bb = ((PointsToAnalysis) getBigBang()); + PointsToAnalysis analysis = getAnalysis(); FixedNode node = invoke.asFixedNode(); MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); @@ -323,8 +327,8 @@ private void handleInvoke(Invoke invoke, SimplifierTool tool) { } else { TypeState receiverTypeState = null; /* If the receiver flow is saturated, its exact type state does not matter. */ - if (invokeFlow.getTargetMethod().hasReceiver() && !methodFlow.isSaturated(bb, invokeFlow.getReceiver())) { - receiverTypeState = methodFlow.foldTypeFlow(bb, invokeFlow.getReceiver()); + if (invokeFlow.getTargetMethod().hasReceiver() && !methodFlow.isSaturated(analysis, invokeFlow.getReceiver())) { + receiverTypeState = methodFlow.foldTypeFlow(analysis, invokeFlow.getReceiver()); } JavaTypeProfile typeProfile = makeTypeProfile(receiverTypeState); @@ -417,11 +421,11 @@ private void devirtualizeInvoke(AnalysisMethod singleCallee, Invoke invoke) { } private boolean isUnreachable(Node branch) { - PointsToAnalysis bb = ((PointsToAnalysis) getBigBang()); + PointsToAnalysis analysis = getAnalysis(); TypeFlow branchFlow = originalFlows.getNodeFlows().get(branch); return branchFlow != null && - !methodFlow.isSaturated(bb, branchFlow) && - methodFlow.foldTypeFlow(bb, branchFlow).isEmpty(); + !methodFlow.isSaturated(analysis, branchFlow) && + methodFlow.foldTypeFlow(analysis, branchFlow).isEmpty(); } private void updateStampInPlace(ValueNode node, Stamp newStamp, SimplifierTool tool) { @@ -470,7 +474,7 @@ private PiNode insertPi(ValueNode input, Stamp piStamp, FixedWithNextNode anchor } private Stamp strengthenStampFromTypeFlow(ValueNode node, TypeFlow nodeFlow, FixedWithNextNode anchorPoint, SimplifierTool tool) { - PointsToAnalysis bb = ((PointsToAnalysis) getBigBang()); + PointsToAnalysis analysis = getAnalysis(); if (node.getStackKind() != JavaKind.Object) { return null; } @@ -481,12 +485,12 @@ private Stamp strengthenStampFromTypeFlow(ValueNode node, TypeFlow nodeFlow, */ return null; } - if (methodFlow.isSaturated(bb, nodeFlow)) { + if (methodFlow.isSaturated(analysis, nodeFlow)) { /* The type flow is saturated, its type state does not matter. */ return null; } - TypeState nodeTypeState = methodFlow.foldTypeFlow(bb, nodeFlow); + TypeState nodeTypeState = methodFlow.foldTypeFlow(analysis, nodeFlow); node.inferStamp(); ObjectStamp oldStamp = (ObjectStamp) node.stamp(NodeView.DEFAULT); AnalysisType oldType = (AnalysisType) oldStamp.type(); @@ -499,7 +503,7 @@ private Stamp strengthenStampFromTypeFlow(ValueNode node, TypeFlow nodeFlow, * stamp is already more precise than the static analysis results. */ List typeStateTypes = new ArrayList<>(nodeTypeState.typesCount()); - for (AnalysisType typeStateType : nodeTypeState.types(bb)) { + for (AnalysisType typeStateType : nodeTypeState.types(analysis)) { if (oldType == null || (oldStamp.isExactType() ? oldType.equals(typeStateType) : oldType.isAssignableFrom(typeStateType))) { typeStateTypes.add(typeStateType); } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityObjectScanner.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityObjectScanner.java index 4e392e49b9b2..85e5dd16d5a2 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityObjectScanner.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityObjectScanner.java @@ -55,7 +55,7 @@ public void forRelocatedPointerFieldValue(JavaConstant receiver, AnalysisField f @Override public void forNullFieldValue(JavaConstant receiver, AnalysisField field) { if (receiver != null) { - bb.markTypeReachable(constantType(bb, receiver)); + bb.markTypeReachable(constantType(receiver)); } bb.markTypeReachable(field.getType()); // System.out.println("Scanning field " + field); @@ -63,8 +63,9 @@ public void forNullFieldValue(JavaConstant receiver, AnalysisField field) { @Override public void forNonNullFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) { - if (receiver != null) - bb.markTypeReachable(constantType(bb, receiver)); + if (receiver != null) { + bb.markTypeReachable(constantType(receiver)); + } bb.markTypeReachable(field.getType()); // System.out.println("Scanning field " + field); } @@ -82,17 +83,17 @@ public void forNonNullArrayElement(JavaConstant array, AnalysisType arrayType, J @Override public void forScannedConstant(JavaConstant scannedValue, ObjectScanner.ScanReason reason) { - AnalysisType type = constantType(bb, scannedValue); + AnalysisType type = constantType(scannedValue); // System.out.println("Scanning constant of type " + type); bb.markTypeInstantiated(type); type.registerAsInHeap(); } - private AnalysisType constantType(BigBang bb, JavaConstant constant) { - return access.lookupJavaType(constantAsObject(bb, constant).getClass()); + private AnalysisType constantType(JavaConstant constant) { + return access.lookupJavaType(constantAsObject(constant).getClass()); } - public Object constantAsObject(BigBang bb, JavaConstant constant) { + private Object constantAsObject(JavaConstant constant) { return bb.getSnippetReflectionProvider().asObject(Object.class, constant); } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java index 05191b5c03f2..de78b7dd6095 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java @@ -95,6 +95,7 @@ public MethodSummary getSummary(BigBang bigBang, StructuredGraph graph) { return new Instance().createSummaryFromGraph(graph); } + @SuppressWarnings("unused") protected void delegateNodeProcessing(Instance instance, Node node) { } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java index 2d2f5e848daa..5266c3f55a45 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java @@ -46,7 +46,6 @@ import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; -import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.PointsToAnalysis; import com.oracle.graal.pointsto.flow.MethodTypeFlow; import com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder; @@ -60,8 +59,6 @@ import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.config.ObjectLayout; import com.oracle.svm.core.monitor.MultiThreadedMonitorSupport; -import com.oracle.svm.core.util.VMError; -import com.oracle.svm.hosted.analysis.Inflation; import com.oracle.svm.hosted.analysis.flow.SVMMethodTypeFlowBuilder; import com.oracle.svm.hosted.classinitialization.ClassInitializationSupport; import com.oracle.svm.hosted.code.CompileQueue; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index 6c2de2028e2d..713a984c0c73 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -554,7 +554,7 @@ private void doRun(Map entryPoints, return; } - dumpAnalysisStats(); +// dumpAnalysisStats(); NativeImageHeap heap; HostedMetaAccess hMetaAccess; @@ -750,11 +750,12 @@ private void dumpAnalysisStats() { } } - private String analysisPrefix() { + private static String analysisPrefix() { return NativeImageOptions.UseExperimentalReachabilityAnalysis.getValue() ? "reachability_" : "points-to_"; } - private void dumpParseTree(CompileQueue compileQueue) { + @SuppressWarnings("unused") + private static void dumpParseTree(CompileQueue compileQueue) { String prefix = analysisPrefix(); List>> entries = CompileQueue.parseTree.entrySet().stream().sorted(Comparator.comparing(entry -> entry.getKey().format(METHOD_FORMAT))) .collect(Collectors.toList()); @@ -779,11 +780,12 @@ private List getCallees(AnalysisMethod method) { throw VMError.shouldNotReachHere(); } - private List getCalleesP(NativeImagePointsToAnalysis bb, AnalysisMethod method) { + @SuppressWarnings("unused") + private static List getCalleesP(NativeImagePointsToAnalysis bb, AnalysisMethod method) { return method.getTypeFlow().getInvokes().stream().flatMap(it -> it.getCallees().stream()).collect(Collectors.toList()); } - private List getCalleesR(NativeImageReachabilityAnalysis bb, AnalysisMethod method) { + private static List getCalleesR(NativeImageReachabilityAnalysis bb, AnalysisMethod method) { MethodSummary summary = bb.summaries.get(method); if (summary == null) { // System.err.println("Don't have a summary for " + method); @@ -793,10 +795,6 @@ private List getCalleesR(NativeImageReachabilityAnalysis bb, Ana Collections.addAll(callees, summary.implementationInvokedMethods); for (AnalysisMethod invokedMethod : summary.invokedMethods) { AnalysisType clazz = invokedMethod.getDeclaringClass(); - // todo solve instantiated subtypes with interfaces! - // java.util.Collections$UnmodifiableList.equals(java.lang.Object) - // java.util.List.equals - // declaring type is List - interface - has no instantiated subtypes atm for (AnalysisType subtype : clazz.getInstantiatedSubtypes()) { AnalysisMethod resolved = subtype.resolveConcreteMethod(invokedMethod, clazz); if (resolved != null) { @@ -807,7 +805,8 @@ private List getCalleesR(NativeImageReachabilityAnalysis bb, Ana return callees; } - private String dumpChain(AnalysisMethod method) { + @SuppressWarnings("unused") + private static String dumpChain(AnalysisMethod method) { ArrayList methods = new ArrayList<>(); Set seen = new HashSet<>(); @@ -819,7 +818,7 @@ private String dumpChain(AnalysisMethod method) { return serializePath(methods, builder); } - private String serializePath(ArrayList methods, StringBuilder builder) { + private static String serializePath(ArrayList methods, StringBuilder builder) { for (int i = methods.size() - 1; i >= 0; i--) { builder.append(methods.get(i)); if (i != 0) { @@ -829,7 +828,7 @@ private String serializePath(ArrayList methods, StringBuilder builder) { return builder.toString(); } - private boolean dfs(AnalysisMethod method, ArrayList methods, Set seen) { + private static boolean dfs(AnalysisMethod method, ArrayList methods, Set seen) { String name = method.format("%H.%n(%P)"); if (!seen.add(name)) { return false; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/Inflation.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/Inflation.java index a0120b86dd3e..629da27f5478 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/Inflation.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/Inflation.java @@ -44,6 +44,7 @@ public interface Inflation extends BigBang { AnnotationSubstitutionProcessor getAnnotationSubstitutionProcessor(); + @Override SubstrateReplacements getReplacements(); @Override diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java index 6eaac229f081..5040e8414621 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java @@ -76,8 +76,8 @@ public class NativeImageReachabilityAnalysis extends ReachabilityAnalysis implem private Set handledUnknownValueFields = ConcurrentHashMap.newKeySet(); private Map genericInterfacesMap = new ConcurrentHashMap<>(); - private Map annotatedInterfacesMap = new ConcurrentHashMap<>();; - private Map interfacesEncodings = new ConcurrentHashMap<>();; + private Map annotatedInterfacesMap = new ConcurrentHashMap<>(); + private Map interfacesEncodings = new ConcurrentHashMap<>(); private final AnnotationSubstitutionProcessor annotationSubstitutionProcessor; private final boolean strengthenGraalGraphs; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java index e19bc34f1dee..d0ddf7ada531 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java @@ -412,7 +412,7 @@ public void finish(DebugContext debug) { * but are no longer reachable now. */ for (HostedMethod method : universe.getMethods()) { -// method.wrapped.setAnalyzedGraph(null); + method.wrapped.setAnalyzedGraph(null); } if (SubstrateOptions.AOTInline.getValue() && SubstrateOptions.AOTTrivialInline.getValue()) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/StrengthenStampsPhase.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/StrengthenStampsPhase.java index a20a13eb947d..125ce536fdf0 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/StrengthenStampsPhase.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/StrengthenStampsPhase.java @@ -85,7 +85,7 @@ protected void run(StructuredGraph graph) { Stamp newStamp = strengthen(node.stamp(NodeView.DEFAULT)); if (newStamp != null) { - // assert !parseOnce : "Must be done by StrengthenGraphs"; + assert !parseOnce : "Must be done by StrengthenGraphs"; node.setStamp(newStamp); } } @@ -98,7 +98,7 @@ protected void run(StructuredGraph graph) { InstanceOfNode node = (InstanceOfNode) n; ObjectStamp newStamp = (ObjectStamp) strengthen(node.getCheckedStamp()); if (newStamp != null) { - // assert !parseOnce : "Must be done by StrengthenGraphs"; + assert !parseOnce : "Must be done by StrengthenGraphs"; node.replaceAndDelete(graph.addOrUniqueWithInputs(InstanceOfNode.createHelper(newStamp, node.getValue(), node.profile(), node.getAnchor()))); } @@ -106,7 +106,7 @@ protected void run(StructuredGraph graph) { PiNode node = (PiNode) n; Stamp newStamp = strengthen(node.piStamp()); if (newStamp != null) { - // assert !parseOnce : "Must be done by StrengthenGraphs"; + assert !parseOnce : "Must be done by StrengthenGraphs"; node.strengthenPiStamp(newStamp); } } @@ -166,7 +166,7 @@ private void updateStamp(ValueNode node, JavaTypeProfile typeProfile) { if (typeProfile != null) { Stamp newStamp = strengthenStamp(node, typeProfile); if (!newStamp.equals(node.stamp(NodeView.DEFAULT))) { - // assert !parseOnce : "Must be done by StrengthenGraphs"; + assert !parseOnce : "Must be done by StrengthenGraphs"; node.getDebug().log("STAMP UPDATE method %s node %s old %s new %s\n", node.graph().method().format("%H.%n(%p)"), node, node.stamp(NodeView.DEFAULT), newStamp); node.setStamp(newStamp); } From 3dc7febc4cb7c92f1b2bc305bb2a122978c740da Mon Sep 17 00:00:00 2001 From: David Kozak Date: Mon, 25 Oct 2021 16:54:03 +0200 Subject: [PATCH 33/65] various fixes --- .../src/com/oracle/graal/reachability/ReachabilityAnalysis.java | 1 + .../src/com/oracle/svm/core/code/RuntimeCodeCache.java | 1 + .../src/com/oracle/svm/hosted/NativeImageGenerator.java | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index ed952413e5a2..98bfeb52aea4 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -337,6 +337,7 @@ public void runAnalysis(DebugContext debugContext, Function boolean visitCode(T codeInfo); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index 713a984c0c73..c63ffad13953 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -629,7 +629,7 @@ private void doRun(Map entryPoints, compileQueue.finish(debug); System.out.println("Number of parsed methods: " + CompileQueue.parsedMethods.size()); System.out.println("Number of compiled methods: " + CompileQueue.compiledMethods.size()); - dumpParseTree(compileQueue); +// dumpParseTree(compileQueue); /* release memory taken by graphs for the image writing */ hUniverse.getMethods().forEach(HostedMethod::clear); From 07152852933d138cb381b07cad2c2b432cd67131 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Tue, 2 Nov 2021 11:44:12 +0100 Subject: [PATCH 34/65] refactor NativeImageReachabilityAnalysis to reduce code redundancy --- .../pointsto/AbstractAnalysisEngine.java | 2 +- .../NativeImageReachabilityAnalysis.java | 422 +----------------- 2 files changed, 4 insertions(+), 420 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java index 5d5ccb83b617..23f92d063e12 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java @@ -61,7 +61,7 @@ public abstract class AbstractAnalysisEngine implements BigBang { protected final HostVM hostVM; protected final ForkJoinPool executorService; private final Runnable heartbeatCallback; - private final UnsupportedFeatures unsupportedFeatures; + protected final UnsupportedFeatures unsupportedFeatures; protected final DebugContext debug; protected final OptionValues options; protected final AnalysisUniverse universe; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java index 5040e8414621..2a2d9678a6dc 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java @@ -25,61 +25,39 @@ package com.oracle.svm.hosted.analysis; import com.oracle.graal.pointsto.ObjectScanner; -import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException; import com.oracle.graal.pointsto.meta.AnalysisField; -import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.graal.pointsto.meta.HostedProviders; -import com.oracle.graal.pointsto.util.AnalysisError; import com.oracle.graal.reachability.MethodSummaryProvider; import com.oracle.graal.reachability.ReachabilityAnalysis; import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.annotate.UnknownObjectField; import com.oracle.svm.core.annotate.UnknownPrimitiveField; import com.oracle.svm.core.graal.meta.SubstrateReplacements; -import com.oracle.svm.core.hub.AnnotatedSuperInfo; -import com.oracle.svm.core.hub.AnnotationsEncoding; -import com.oracle.svm.core.hub.DynamicHub; -import com.oracle.svm.core.hub.GenericInfo; import com.oracle.svm.core.meta.SubstrateObjectConstant; import com.oracle.svm.hosted.SVMHost; -import com.oracle.svm.hosted.meta.HostedType; import com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaType; import org.graalvm.compiler.options.OptionValues; import org.graalvm.word.WordBase; -import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.MalformedParameterizedTypeException; import java.lang.reflect.Modifier; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ForkJoinPool; -import java.util.stream.Collectors; import static jdk.vm.ci.common.JVMCIError.shouldNotReachHere; public class NativeImageReachabilityAnalysis extends ReachabilityAnalysis implements Inflation { private Set handledUnknownValueFields = ConcurrentHashMap.newKeySet(); - private Map genericInterfacesMap = new ConcurrentHashMap<>(); - private Map annotatedInterfacesMap = new ConcurrentHashMap<>(); - private Map interfacesEncodings = new ConcurrentHashMap<>(); - private final AnnotationSubstitutionProcessor annotationSubstitutionProcessor; + private final DynamicHubInitializer dynamicHubInitializer; private final boolean strengthenGraalGraphs; public NativeImageReachabilityAnalysis(OptionValues options, AnalysisUniverse universe, HostedProviders providers, AnnotationSubstitutionProcessor annotationSubstitutionProcessor, @@ -88,6 +66,7 @@ public NativeImageReachabilityAnalysis(OptionValues options, AnalysisUniverse un super(options, universe, providers, universe.hostVM(), executor, heartbeatCallback, new SubstrateUnsupportedFeatures(), methodSummaryProvider); this.annotationSubstitutionProcessor = annotationSubstitutionProcessor; this.strengthenGraalGraphs = SubstrateOptions.parseOnce(); + this.dynamicHubInitializer = new DynamicHubInitializer(universe, metaAccess, unsupportedFeatures, providers.getConstantReflection()); } @Override @@ -102,9 +81,8 @@ public AnnotationSubstitutionProcessor getAnnotationSubstitutionProcessor() { @Override protected void checkObjectGraph(ObjectScanner objectScanner) { - // todo refactor into a common class instead of this ugly copy universe.getFields().forEach(this::handleUnknownValueField); - universe.getTypes().stream().filter(AnalysisType::isReachable).forEach(this::checkType); + universe.getTypes().stream().filter(AnalysisType::isReachable).forEach(dynamicHubInitializer::initializeMetaData); /* Scan hubs of all types that end up in the native image. */ universe.getTypes().stream().filter(AnalysisType::isReachable).forEach(type -> scanHub(objectScanner, type)); @@ -114,9 +92,6 @@ protected void checkObjectGraph(ObjectScanner objectScanner) { public void cleanupAfterAnalysis() { super.cleanupAfterAnalysis(); handledUnknownValueFields = null; - genericInterfacesMap = null; - annotatedInterfacesMap = null; - interfacesEncodings = null; } @Override @@ -134,318 +109,6 @@ public void checkUserLimitations() { // todo } - // todo remove ugly copy paste from this class - - public void checkType(AnalysisType type) { - assert type.isReachable(); - DynamicHub hub = getHostVM().dynamicHub(type); - if (hub.getGenericInfo() == null) { - fillGenericInfo(type, hub); - } - if (hub.getAnnotatedSuperInfo() == null) { - fillAnnotatedSuperInfo(type, hub); - } - - if (type.getJavaKind() == JavaKind.Object) { - if (type.isArray()) { - hub.getComponentHub().setArrayHub(hub); - } - - try { - AnalysisType enclosingType = type.getEnclosingType(); - if (enclosingType != null) { - hub.setEnclosingClass(getHostVM().dynamicHub(enclosingType)); - } - } catch (UnsupportedFeatureException ex) { - getUnsupportedFeatures().addMessage(type.toJavaName(true), null, ex.getMessage(), null, ex); - } - - if (hub.getInterfacesEncoding() == null) { - fillInterfaces(type, hub); - } - - /* - * Support for Java annotations. - */ - try { - /* - * Get the annotations from the wrapped type since AnalysisType.getAnnotations() - * defends against JDK-7183985 and we want to get the original behavior. - */ - Annotation[] annotations = type.getWrappedWithoutResolve().getAnnotations(); - Annotation[] declared = type.getWrappedWithoutResolve().getDeclaredAnnotations(); - hub.setAnnotationsEncoding(encodeAnnotations(metaAccess, annotations, declared, hub.getAnnotationsEncoding())); - } catch (ArrayStoreException e) { - /* If we hit JDK-7183985 just encode the exception. */ - hub.setAnnotationsEncoding(e); - } - - /* - * Support for Java enumerations. - */ - if (type.isEnum() && hub.shouldInitEnumConstants()) { - if (getHostVM().getClassInitializationSupport().shouldInitializeAtRuntime(type)) { - hub.initEnumConstantsAtRuntime(type.getJavaClass()); - } else { - /* - * We want to retrieve the enum constant array that is maintained as a private - * static field in the enumeration class. We do not want a copy because that - * would mean we have the array twice in the native image: as the static field, - * and in the enumConstant field of DynamicHub. The only way to get the original - * value is via a reflective field access, and we even have to guess the field - * name. - */ - AnalysisField found = null; - for (AnalysisField f : type.getStaticFields()) { - if (f.getName().endsWith("$VALUES")) { - if (found != null) { - /* - * Enumeration has more than one static field with enumeration - * values. Bailout and use Class.getEnumConstants() to get the value - * instead. - */ - found = null; - break; - } - found = f; - } - } - Enum[] enumConstants; - if (found == null) { - /* - * We could not find a unique $VALUES field, so we use the value returned by - * Class.getEnumConstants(). This is not ideal since - * Class.getEnumConstants() returns a copy of the array, so we will have two - * arrays with the same content in the image heap, but it is better than - * failing image generation. - */ - enumConstants = (Enum[]) type.getJavaClass().getEnumConstants(); - } else { - enumConstants = (Enum[]) SubstrateObjectConstant.asObject(getConstantReflectionProvider().readFieldValue(found, null)); - assert enumConstants != null; - } - hub.initEnumConstants(enumConstants); - } - } - } - } - - static class GenericInterfacesEncodingKey { - final Type[] interfaces; - - GenericInterfacesEncodingKey(Type[] aInterfaces) { - this.interfaces = aInterfaces; - } - - @Override - public boolean equals(Object obj) { - return obj instanceof GenericInterfacesEncodingKey && Arrays.equals(interfaces, ((GenericInterfacesEncodingKey) obj).interfaces); - } - - @Override - public int hashCode() { - return Arrays.hashCode(interfaces); - } - } - - /** Modified copy of {@link Arrays#equals(Object[], Object[])}. */ - private static boolean shallowEquals(Object[] a, Object[] a2) { - if (a == a2) { - return true; - } else if (a == null || a2 == null) { - return false; - } - int length = a.length; - if (a2.length != length) { - return false; - } - for (int i = 0; i < length; i++) { - /* Modification: use reference equality. */ - if (a[i] != a2[i]) { - return false; - } - } - return true; - } - - /** Modified copy of {@link Arrays#hashCode(Object[])}. */ - private static int shallowHashCode(Object[] a) { - if (a == null) { - return 0; - } - int result = 1; - - for (Object element : a) { - /* Modification: use identity hash code. */ - result = 31 * result + System.identityHashCode(element); - } - return result; - } - - static class AnnotatedInterfacesEncodingKey { - final AnnotatedType[] interfaces; - - AnnotatedInterfacesEncodingKey(AnnotatedType[] aInterfaces) { - this.interfaces = aInterfaces; - } - - /* - * JDK 12 introduced a broken implementation of hashCode() and equals() for the - * implementation classes of annotated types, leading to an infinite recursion. Tracked as - * JDK-8224012. As a workaround, we use shallow implementations that only depend on the - * identity hash code and reference equality. This is the same behavior as on JDK 8 and JDK - * 11 anyway. - */ - - @Override - public boolean equals(Object obj) { - return obj instanceof AnnotatedInterfacesEncodingKey && - shallowEquals(interfaces, ((AnnotatedInterfacesEncodingKey) obj).interfaces); - } - - @Override - public int hashCode() { - return shallowHashCode(interfaces); - } - } - - private void fillGenericInfo(AnalysisType type, DynamicHub hub) { - Class javaClass = type.getJavaClass(); - - TypeVariable[] typeParameters = javaClass.getTypeParameters(); - - Type[] allGenericInterfaces; - try { - allGenericInterfaces = javaClass.getGenericInterfaces(); - } catch (MalformedParameterizedTypeException | TypeNotPresentException | LinkageError t) { - /* - * Loading generic interfaces can fail due to missing types. Ignore the exception and - * return an empty array. - */ - allGenericInterfaces = new Type[0]; - } - - Type[] genericInterfaces = Arrays.stream(allGenericInterfaces).filter(this::isTypeAllowed).toArray(Type[]::new); - Type[] cachedGenericInterfaces; - try { - cachedGenericInterfaces = genericInterfacesMap.computeIfAbsent(new NativeImageReachabilityAnalysis.GenericInterfacesEncodingKey(genericInterfaces), k -> genericInterfaces); - } catch (MalformedParameterizedTypeException | TypeNotPresentException | LinkageError t) { - /* - * Computing the hash code of generic interfaces can fail due to missing types. Ignore - * the exception and proceed without caching. De-duplication of generic interfaces is an - * optimization and not necessary for correctness. - */ - cachedGenericInterfaces = genericInterfaces; - } - - Type genericSuperClass; - try { - genericSuperClass = javaClass.getGenericSuperclass(); - } catch (MalformedParameterizedTypeException | TypeNotPresentException | LinkageError t) { - /* - * Loading the generic super class can fail due to missing types. Ignore the exception - * and return null. - */ - genericSuperClass = null; - } - if (!isTypeAllowed(genericSuperClass)) { - genericSuperClass = null; - } - hub.setGenericInfo(GenericInfo.factory(typeParameters, cachedGenericInterfaces, genericSuperClass)); - } - - private void fillAnnotatedSuperInfo(AnalysisType type, DynamicHub hub) { - Class javaClass = type.getJavaClass(); - - AnnotatedType annotatedSuperclass; - try { - annotatedSuperclass = javaClass.getAnnotatedSuperclass(); - } catch (MalformedParameterizedTypeException | TypeNotPresentException | LinkageError t) { - /* - * Loading the annotated super class can fail due to missing types. Ignore the exception - * and return null. - */ - annotatedSuperclass = null; - } - if (annotatedSuperclass != null && !isTypeAllowed(annotatedSuperclass.getType())) { - annotatedSuperclass = null; - } - - AnnotatedType[] allAnnotatedInterfaces; - try { - allAnnotatedInterfaces = javaClass.getAnnotatedInterfaces(); - } catch (MalformedParameterizedTypeException | TypeNotPresentException | LinkageError t) { - /* - * Loading annotated interfaces can fail due to missing types. Ignore the exception and - * return an empty array. - */ - allAnnotatedInterfaces = new AnnotatedType[0]; - } - - AnnotatedType[] annotatedInterfaces = Arrays.stream(allAnnotatedInterfaces) - .filter(ai -> isTypeAllowed(ai.getType())).toArray(AnnotatedType[]::new); - AnnotatedType[] cachedAnnotatedInterfaces = annotatedInterfacesMap.computeIfAbsent( - new NativeImageReachabilityAnalysis.AnnotatedInterfacesEncodingKey(annotatedInterfaces), k -> annotatedInterfaces); - hub.setAnnotatedSuperInfo(AnnotatedSuperInfo.factory(annotatedSuperclass, cachedAnnotatedInterfaces)); - } - - private boolean isTypeAllowed(Type t) { - if (t instanceof Class) { - Optional resolved = metaAccess.optionalLookupJavaType((Class) t); - return resolved.isPresent() && hostVM.platformSupported(universe, resolved.get()); - } - return true; - } - - class InterfacesEncodingKey { - final AnalysisType[] aInterfaces; - - InterfacesEncodingKey(AnalysisType[] aInterfaces) { - this.aInterfaces = aInterfaces; - } - - DynamicHub[] createHubs() { - SVMHost svmHost = (SVMHost) hostVM; - DynamicHub[] hubs = new DynamicHub[aInterfaces.length]; - for (int i = 0; i < hubs.length; i++) { - hubs[i] = svmHost.dynamicHub(aInterfaces[i]); - } - return hubs; - } - - @Override - public boolean equals(Object obj) { - return obj instanceof NativeImageReachabilityAnalysis.InterfacesEncodingKey && Arrays.equals(aInterfaces, ((NativeImageReachabilityAnalysis.InterfacesEncodingKey) obj).aInterfaces); - } - - @Override - public int hashCode() { - return Arrays.hashCode(aInterfaces); - } - } - - /** - * Fill array returned by Class.getInterfaces(). - */ - private void fillInterfaces(AnalysisType type, DynamicHub hub) { - SVMHost svmHost = (SVMHost) hostVM; - - AnalysisType[] aInterfaces = type.getInterfaces(); - if (aInterfaces.length == 0) { - hub.setInterfacesEncoding(null); - } else if (aInterfaces.length == 1) { - hub.setInterfacesEncoding(svmHost.dynamicHub(aInterfaces[0])); - } else { - /* - * Many interfaces arrays are the same, e.g., all arrays implement the same two - * interfaces. We want to avoid duplicate arrays with the same content in the native - * image heap. - */ - hub.setInterfacesEncoding( - interfacesEncodings.computeIfAbsent(new NativeImageReachabilityAnalysis.InterfacesEncodingKey(aInterfaces), InterfacesEncodingKey::createHubs)); - } - } - private void scanHub(ObjectScanner objectScanner, AnalysisType type) { SVMHost svmHost = (SVMHost) hostVM; JavaConstant hubConstant = SubstrateObjectConstant.forObject(svmHost.dynamicHub(type)); @@ -542,83 +205,4 @@ private void handleUnknownObjectField(AnalysisField aField, AnalysisType... decl } } - private static Set filterUsedAnnotation(Set used, Annotation[] rest) { - if (rest == null) { - return null; - } - - Set restUsed = new HashSet<>(); - for (Annotation a : rest) { - if (used.contains(a)) { - restUsed.add(a); - } - } - return restUsed; - } - - public static Object encodeAnnotations(AnalysisMetaAccess metaAccess, Annotation[] allAnnotations, Annotation[] declaredAnnotations, Object oldEncoding) { - Object newEncoding; - if (allAnnotations.length == 0 && declaredAnnotations.length == 0) { - newEncoding = null; - } else { - Set all = new HashSet<>(); - Collections.addAll(all, allAnnotations); - Collections.addAll(all, declaredAnnotations); - final Set usedAnnotations = all.stream() - .filter(a -> { - try { - AnalysisType annotationClass = metaAccess.lookupJavaType(a.getClass()); - return isAnnotationUsed(annotationClass); - } catch (AnalysisError.TypeNotFoundError e) { - /* - * Silently ignore the annotation if its type was not discovered - * by the static analysis. - */ - return false; - } - }).collect(Collectors.toSet()); - Set usedDeclared = filterUsedAnnotation(usedAnnotations, declaredAnnotations); - newEncoding = usedAnnotations.size() == 0 - ? null - : AnnotationsEncoding.encodeAnnotations(usedAnnotations, usedDeclared); - } - - /* - * Return newEncoding only if the value is different from oldEncoding. Without this guard, - * for tests that do runtime compilation, the field appears as being continuously updated - * during BigBang.checkObjectGraph. - */ - if (oldEncoding != null && oldEncoding.equals(newEncoding)) { - return oldEncoding; - } else { - return newEncoding; - } - } - - /** - * We only want annotations in the native image heap that are "used" at run time. In our case, - * "used" means that the annotation interface is used at least in a type check. This leaves one - * case where Substrate VM behaves differently than a normal Java VM: When you just query the - * number of annotations on a class, then we might return a lower number. - */ - private static boolean isAnnotationUsed(AnalysisType annotationType) { - if (annotationType.isReachable()) { - return true; - } - assert annotationType.getInterfaces().length == 1 : annotationType; - - AnalysisType annotationInterfaceType = annotationType.getInterfaces()[0]; - return annotationInterfaceType.isReachable(); - } - - public static ResolvedJavaType toWrappedType(ResolvedJavaType type) { - if (type instanceof AnalysisType) { - return ((AnalysisType) type).getWrappedWithoutResolve(); - } else if (type instanceof HostedType) { - return ((HostedType) type).getWrapped().getWrappedWithoutResolve(); - } else { - return type; - } - } - } From 6e4a695ddc083514359d647cbcf3f7d24afa456f Mon Sep 17 00:00:00 2001 From: David Kozak Date: Tue, 23 Nov 2021 11:46:13 +0100 Subject: [PATCH 35/65] method summaries WIP --- .../graal/reachability/MethodSummary.java | 13 ++ .../SerializableMethodSummary.java | 164 +++++++++++++++ .../summaries/DummyHashingStrategy.java | 48 +++++ .../summaries/HashingStrategy.java | 36 ++++ .../reachability/summaries/MethodHash.java | 40 ++++ .../summaries/MethodSummaryStorage.java | 195 ++++++++++++++++++ .../summaries/PersistedSummary.java | 46 +++++ .../summaries/ResolutionStrategy.java | 49 +++++ .../svm/hosted/NativeImageGenerator.java | 16 +- .../svm/hosted/ResolutionStrategyImpl.java | 120 +++++++++++ 10 files changed, 725 insertions(+), 2 deletions(-) create mode 100644 substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SerializableMethodSummary.java create mode 100644 substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/DummyHashingStrategy.java create mode 100644 substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/HashingStrategy.java create mode 100644 substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/MethodHash.java create mode 100644 substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/MethodSummaryStorage.java create mode 100644 substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/PersistedSummary.java create mode 100644 substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/ResolutionStrategy.java create mode 100644 substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResolutionStrategyImpl.java diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java index 132053c42fd4..5c5f2c3f5470 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java @@ -63,6 +63,19 @@ public MethodSummary(AnalysisMethod[] invokedMethods, AnalysisMethod[] implement this.foreignCallSignatures = foreignCallSignatures; } + public MethodSummary(AnalysisMethod[] invokedMethods, AnalysisMethod[] implementationInvokedMethods, AnalysisType[] accessedTypes, AnalysisType[] instantiatedTypes, AnalysisField[] readFields, + AnalysisField[] writtenFields) { + this.invokedMethods = invokedMethods; + this.implementationInvokedMethods = implementationInvokedMethods; + this.accessedTypes = accessedTypes; + this.instantiatedTypes = instantiatedTypes; + this.readFields = readFields; + this.writtenFields = writtenFields; + this.embeddedConstants = new JavaConstant[0]; + this.foreignCallDescriptors = new ForeignCallDescriptor[0]; + this.foreignCallSignatures = new ForeignCallSignature[0]; + } + @Override public String toString() { return "MethodSummary{" + diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SerializableMethodSummary.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SerializableMethodSummary.java new file mode 100644 index 000000000000..b596ecc27b58 --- /dev/null +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SerializableMethodSummary.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.reachability; + +import com.oracle.graal.reachability.summaries.MethodHash; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Objects; + +public class SerializableMethodSummary implements Serializable { + + public SerializableMethodSummary(MethodHash hash, MethodId[] invokedMethods, MethodId[] implementationInvokedMethods, ClassId[] accessedTypes, ClassId[] instantiatedTypes, FieldId[] readFields, + FieldId[] writtenFields) { + this.hash = hash; + this.invokedMethods = invokedMethods; + this.implementationInvokedMethods = implementationInvokedMethods; + this.accessedTypes = accessedTypes; + this.instantiatedTypes = instantiatedTypes; + this.readFields = readFields; + this.writtenFields = writtenFields; + } + + public static class ClassId implements Serializable { + public final String className; + + public ClassId(String className) { + this.className = className; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ClassId classId = (ClassId) o; + return Objects.equals(className, classId.className); + } + + @Override + public int hashCode() { + return Objects.hash(className); + } + + @Override + public String toString() { + return "ClassId{" + + "className='" + className + '\'' + + '}'; + } + } + + public static class MethodId implements Serializable { + public final ClassId classId; + public final String methodName; + + public MethodId(ClassId classId, String methodName) { + this.classId = classId; + this.methodName = methodName; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + MethodId methodId = (MethodId) o; + return Objects.equals(classId, methodId.classId) && Objects.equals(methodName, methodId.methodName); + } + + @Override + public int hashCode() { + return Objects.hash(classId, methodName); + } + + @Override + public String toString() { + return "MethodId{" + + "classId=" + classId + + ", methodName='" + methodName + '\'' + + '}'; + } + } + + public static class FieldId implements Serializable { + public final ClassId classId; + public final String fieldName; + + public FieldId(ClassId classId, String fieldName) { + this.classId = classId; + this.fieldName = fieldName; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + FieldId fieldId = (FieldId) o; + return Objects.equals(classId, fieldId.classId) && Objects.equals(fieldName, fieldId.fieldName); + } + + @Override + public int hashCode() { + return Objects.hash(classId, fieldName); + } + + @Override + public String toString() { + return "FieldId{" + + "classId=" + classId + + ", fieldName='" + fieldName + '\'' + + '}'; + } + } + + public final MethodHash hash; + public final MethodId[] invokedMethods; + public final MethodId[] implementationInvokedMethods; + public final ClassId[] accessedTypes; + public final ClassId[] instantiatedTypes; + public final FieldId[] readFields; + public final FieldId[] writtenFields; + + @Override + public String toString() { + return "SerializableMethodSummary{" + + "hash=" + hash + + ", invokedMethods=" + Arrays.toString(invokedMethods) + + ", implementationInvokedMethods=" + Arrays.toString(implementationInvokedMethods) + + ", accessedTypes=" + Arrays.toString(accessedTypes) + + ", instantiatedTypes=" + Arrays.toString(instantiatedTypes) + + ", readFields=" + Arrays.toString(readFields) + + ", writtenFields=" + Arrays.toString(writtenFields) + + '}'; + } +} diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/DummyHashingStrategy.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/DummyHashingStrategy.java new file mode 100644 index 000000000000..5f58e530ed56 --- /dev/null +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/DummyHashingStrategy.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.reachability.summaries; + +import com.oracle.graal.pointsto.meta.AnalysisMethod; +import com.oracle.graal.reachability.MethodSummary; +import com.oracle.graal.reachability.SerializableMethodSummary; + +import java.util.Arrays; + +public class DummyHashingStrategy implements HashingStrategy { + @Override + public PersistedSummary prepare(AnalysisMethod method, MethodSummary summary) { + long hash = getHash(method); + return new PersistedSummary(summary, new MethodHash(hash)); + } + + @Override + public boolean isValid(AnalysisMethod method, SerializableMethodSummary summary) { + return summary.hash.getValue() == getHash(method); + } + + private long getHash(AnalysisMethod method) { + return Arrays.hashCode(method.getCode()); + } +} diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/HashingStrategy.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/HashingStrategy.java new file mode 100644 index 000000000000..32fb4bf45587 --- /dev/null +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/HashingStrategy.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.reachability.summaries; + +import com.oracle.graal.pointsto.meta.AnalysisMethod; +import com.oracle.graal.reachability.MethodSummary; +import com.oracle.graal.reachability.SerializableMethodSummary; + +public interface HashingStrategy { + + PersistedSummary prepare(AnalysisMethod method, MethodSummary summary); + + boolean isValid(AnalysisMethod method, SerializableMethodSummary summary); +} diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/MethodHash.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/MethodHash.java new file mode 100644 index 000000000000..25634c00d9e8 --- /dev/null +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/MethodHash.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.reachability.summaries; + +import java.io.Serializable; + +public final class MethodHash implements Serializable { + + private final long value; + + MethodHash(long value) { + this.value = value; + } + + public long getValue() { + return value; + } +} diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/MethodSummaryStorage.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/MethodSummaryStorage.java new file mode 100644 index 000000000000..636f32cc32ac --- /dev/null +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/MethodSummaryStorage.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.reachability.summaries; + +import com.oracle.graal.pointsto.BigBang; +import com.oracle.graal.pointsto.meta.AnalysisField; +import com.oracle.graal.pointsto.meta.AnalysisMethod; +import com.oracle.graal.pointsto.meta.AnalysisType; +import com.oracle.graal.reachability.MethodSummary; +import com.oracle.graal.reachability.MethodSummaryProvider; +import com.oracle.graal.reachability.SerializableMethodSummary; +import com.oracle.graal.reachability.SimpleInMemoryMethodSummaryProvider; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionType; +import org.graalvm.compiler.options.OptionValues; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; + +public class MethodSummaryStorage implements MethodSummaryProvider { + + public MethodSummaryStorage(ResolutionStrategy resolutionStrategy, SimpleInMemoryMethodSummaryProvider simpleInMemoryMethodSummaryProvider, OptionValues options) { + this.resolutionStrategy = resolutionStrategy; + this.simpleInMemoryMethodSummaryProvider = simpleInMemoryMethodSummaryProvider; + this.options = options; + } + + public static class Options { + @Option(help = "Summary storage file", type = OptionType.User)// + public static final OptionKey SummaryFile = new OptionKey<>(""); + } + + private final Map storage = new ConcurrentHashMap<>(); + + private final HashingStrategy hashingStrategy = new DummyHashingStrategy(); + + private final ResolutionStrategy resolutionStrategy; + private final SimpleInMemoryMethodSummaryProvider simpleInMemoryMethodSummaryProvider; + private final OptionValues options; + + @Override + public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { + PersistedSummary persistedSummary = storage.get(method); + if (persistedSummary != null) { + return persistedSummary.getSummary(); + } + MethodSummary summary = simpleInMemoryMethodSummaryProvider.getSummary(bb, method); + PersistedSummary preparedSummary = hashingStrategy.prepare(method, summary); + storage.put(method, preparedSummary); + return summary; + } + + @Override + public MethodSummary getSummary(BigBang bigBang, StructuredGraph graph) { + return simpleInMemoryMethodSummaryProvider.getSummary(bigBang, graph); + } + + public void loadData() { + String summaryFileName = Options.SummaryFile.getValue(options); + if (summaryFileName.isEmpty()) { + return; + } + try (ObjectInputStream stream = new ObjectInputStream(new FileInputStream(summaryFileName))) { + Map summaries = (Map) stream.readObject(); + processSummaryFile(summaries); + } catch (IOException | ClassNotFoundException e) { + e.printStackTrace(); + } + } + + private void processSummaryFile(Map summaries) { + for (Map.Entry methodEntry : summaries.entrySet()) { + System.out.println("!! " + methodEntry.getKey()); + AnalysisMethod analysisMethod = resolutionStrategy.resolveMethod(methodEntry.getKey()); + if (analysisMethod == null) { + err("Could not resolve method " + methodEntry.getKey()); + continue; + } + try { + if (hashingStrategy.isValid(analysisMethod, methodEntry.getValue())) { + MethodSummary resolvedSummary = resolveSummary(methodEntry.getValue()); + storage.put(analysisMethod, hashingStrategy.prepare(analysisMethod, resolvedSummary)); + } else { + err("Method summary for " + analysisMethod + " is not valid."); + } + } catch (RuntimeException ex) { + err("Cannot resolve summary for " + analysisMethod + ": " + ex.getMessage()); + continue; + } + } + } + + private MethodSummary resolveSummary(SerializableMethodSummary value) { + AnalysisMethod[] invokedMethods = resolveHelper(value.invokedMethods, resolutionStrategy::resolveMethod, AnalysisMethod.class); + AnalysisMethod[] implementationInvokedMethods = resolveHelper(value.implementationInvokedMethods, resolutionStrategy::resolveMethod, AnalysisMethod.class); + AnalysisType[] accessedTypes = resolveHelper(value.accessedTypes, resolutionStrategy::resolveClass, AnalysisType.class); + AnalysisType[] instantiatedTypes = resolveHelper(value.instantiatedTypes, resolutionStrategy::resolveClass, AnalysisType.class); + AnalysisField[] readFields = resolveHelper(value.readFields, resolutionStrategy::resolveField, AnalysisField.class); + AnalysisField[] writtenFields = resolveHelper(value.writtenFields, resolutionStrategy::resolveField, AnalysisField.class); + return new MethodSummary(invokedMethods, implementationInvokedMethods, accessedTypes, instantiatedTypes, readFields, writtenFields); + } + + public Type[] resolveHelper(SerializedType[] inputArray, Function resolver, Class typeTag) { + Type[] res = (Type[]) Array.newInstance(typeTag, inputArray.length); + for (int i = 0; i < inputArray.length; i++) { + SerializedType elem = inputArray[i]; + Type resolved = resolver.apply(elem); + if (resolved == null) { + throw new RuntimeException("Failed to resolve " + elem); + } + res[i] = resolved; + } + return res; + } + + public void persistData() { + String summaryFileName = Options.SummaryFile.getValue(options); + if (summaryFileName.isEmpty()) { + return; + } + try (ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream(summaryFileName))) { + stream.writeObject(serializeStorage()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private Map serializeStorage() { + Map serializableMap = new HashMap<>(); + for (Map.Entry entry : storage.entrySet()) { + if (!canSerialize(entry.getValue())) { + err("Can't serialize a summary"); + return null; + } + SerializableMethodSummary summary = serializeSummary(entry.getValue()); + serializableMap.put(resolutionStrategy.getId(entry.getKey()), summary); + } + return serializableMap; + } + + private SerializableMethodSummary serializeSummary(PersistedSummary persistedSummary) { + MethodSummary summary = persistedSummary.getSummary(); + + SerializableMethodSummary.MethodId[] invokedMethods = Arrays.stream(summary.invokedMethods).map(resolutionStrategy::getId).toArray(SerializableMethodSummary.MethodId[]::new); + SerializableMethodSummary.MethodId[] implInvokedMethods = Arrays.stream(summary.implementationInvokedMethods).map(resolutionStrategy::getId).toArray(SerializableMethodSummary.MethodId[]::new); + SerializableMethodSummary.ClassId[] accessedTypes = Arrays.stream(summary.accessedTypes).map(resolutionStrategy::getId).toArray(SerializableMethodSummary.ClassId[]::new); + SerializableMethodSummary.ClassId[] instantiatedTypes = Arrays.stream(summary.instantiatedTypes).map(resolutionStrategy::getId).toArray(SerializableMethodSummary.ClassId[]::new); + SerializableMethodSummary.FieldId[] readFields = Arrays.stream(summary.readFields).map(resolutionStrategy::getId).toArray(SerializableMethodSummary.FieldId[]::new); + SerializableMethodSummary.FieldId[] writtenFields = Arrays.stream(summary.writtenFields).map(resolutionStrategy::getId).toArray(SerializableMethodSummary.FieldId[]::new); + return new SerializableMethodSummary(persistedSummary.getHash(), invokedMethods, implInvokedMethods, accessedTypes, instantiatedTypes, readFields, writtenFields); + } + + private boolean canSerialize(PersistedSummary persistedSummary) { + MethodSummary summary = persistedSummary.getSummary(); + // todo implement + return true; + } + + public void err(String msg) { + System.err.println(msg); + } +} diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/PersistedSummary.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/PersistedSummary.java new file mode 100644 index 000000000000..f9813096492e --- /dev/null +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/PersistedSummary.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.reachability.summaries; + +import com.oracle.graal.reachability.MethodSummary; + +public class PersistedSummary { + + private final MethodSummary summary; + private final MethodHash hash; + + public PersistedSummary(MethodSummary summary, MethodHash hash) { + this.summary = summary; + this.hash = hash; + } + + public MethodSummary getSummary() { + return summary; + } + + public MethodHash getHash() { + return hash; + } +} diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/ResolutionStrategy.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/ResolutionStrategy.java new file mode 100644 index 000000000000..512240e50802 --- /dev/null +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/ResolutionStrategy.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.reachability.summaries; + +import com.oracle.graal.pointsto.meta.AnalysisField; +import com.oracle.graal.pointsto.meta.AnalysisMethod; +import com.oracle.graal.pointsto.meta.AnalysisType; +import com.oracle.graal.reachability.SerializableMethodSummary; + +public interface ResolutionStrategy { + + AnalysisType resolveClass(SerializableMethodSummary.ClassId classId); + + AnalysisMethod resolveMethod(AnalysisType clazz, SerializableMethodSummary.MethodId methodId); + + AnalysisMethod resolveMethod(SerializableMethodSummary.MethodId methodId); + + AnalysisField resolveField(AnalysisType clazz, SerializableMethodSummary.FieldId fieldId); + + AnalysisField resolveField(SerializableMethodSummary.FieldId fieldId); + + SerializableMethodSummary.ClassId getId(AnalysisType type); + + SerializableMethodSummary.MethodId getId(AnalysisMethod method); + + SerializableMethodSummary.FieldId getId(AnalysisField type); +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index c63ffad13953..f0cdea31f625 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -64,6 +64,8 @@ import com.oracle.graal.pointsto.meta.PointsToAnalysisMethod; import com.oracle.graal.pointsto.infrastructure.WrappedElement; import com.oracle.graal.reachability.MethodSummary; +import com.oracle.graal.reachability.SimpleInMemoryMethodSummaryProvider; +import com.oracle.graal.reachability.summaries.MethodSummaryStorage; import com.oracle.svm.core.code.ImageCodeInfo; import com.oracle.svm.hosted.analysis.NativeImageReachabilityAnalysis; import org.graalvm.collections.EconomicSet; @@ -326,6 +328,8 @@ public class NativeImageGenerator { private final Map> buildArtifacts = new EnumMap<>(ArtifactType.class); + private MethodSummaryStorage methodSummaryStorage; + public NativeImageGenerator(ImageClassLoader loader, HostedOptionProvider optionProvider, Pair mainEntryPoint, ProgressReporter reporter) { this.loader = loader; this.mainEntryPoint = mainEntryPoint; @@ -705,6 +709,10 @@ private void doRun(Map entryPoints, if (SubstrateOptions.BuildOutputBreakdowns.getValue()) { ProgressReporter.singleton().printBreakdowns(compileQueue.getCompilationTasks(), image.getHeap().getObjects()); } + + if (methodSummaryStorage != null) { + methodSummaryStorage.persistData(); + } } } @@ -1193,7 +1201,7 @@ public static void initializeBigBang(Inflation bb, OptionValues options, Feature } } - public static Inflation createBigBang(OptionValues options, TargetDescription target, AnalysisUniverse aUniverse, ForkJoinPool analysisExecutor, + public Inflation createBigBang(OptionValues options, TargetDescription target, AnalysisUniverse aUniverse, ForkJoinPool analysisExecutor, Runnable heartbeatCallback, AnalysisMetaAccess aMetaAccess, AnalysisConstantReflectionProvider aConstantReflection, WordTypes aWordTypes, SnippetReflectionProvider aSnippetReflection, AnnotationSubstitutionProcessor annotationSubstitutionProcessor, ForeignCallsProvider aForeignCalls, ClassInitializationSupport classInitializationSupport, Providers originalProviders) { @@ -1218,8 +1226,12 @@ public static Inflation createBigBang(OptionValues options, TargetDescription ta aSnippetReflection, aWordTypes, platformConfig, aMetaAccessExtensionProvider, originalProviders.getLoopsDataProvider()); if (NativeImageOptions.UseExperimentalReachabilityAnalysis.getValue()) { + SimpleInMemoryMethodSummaryProvider simpleInMemoryMethodSummaryProvider = ((SimpleInMemoryMethodSummaryProvider) HostedConfiguration.instance().createMethodSummaryProvider(aUniverse, + aMetaAccess)); + methodSummaryStorage = new MethodSummaryStorage(new ResolutionStrategyImpl(loader, aMetaAccess), simpleInMemoryMethodSummaryProvider, options); + methodSummaryStorage.loadData(); return new NativeImageReachabilityAnalysis(options, aUniverse, aProviders, annotationSubstitutionProcessor, analysisExecutor, heartbeatCallback, - HostedConfiguration.instance().createMethodSummaryProvider(aUniverse, aMetaAccess)); + methodSummaryStorage); } return new NativeImagePointsToAnalysis(options, aUniverse, aProviders, annotationSubstitutionProcessor, analysisExecutor, heartbeatCallback, new SubstrateUnsupportedFeatures()); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResolutionStrategyImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResolutionStrategyImpl.java new file mode 100644 index 000000000000..c8a64f8d2344 --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResolutionStrategyImpl.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.hosted; + +import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException; +import com.oracle.graal.pointsto.meta.AnalysisField; +import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; +import com.oracle.graal.pointsto.meta.AnalysisMethod; +import com.oracle.graal.pointsto.meta.AnalysisType; +import com.oracle.graal.reachability.SerializableMethodSummary; +import com.oracle.graal.reachability.summaries.ResolutionStrategy; + +public class ResolutionStrategyImpl implements ResolutionStrategy { + private final ImageClassLoader loader; + private final AnalysisMetaAccess metaAccess; + + public ResolutionStrategyImpl(ImageClassLoader loader, AnalysisMetaAccess metaAccess) { + this.loader = loader; + this.metaAccess = metaAccess; + } + + @Override + public AnalysisType resolveClass(SerializableMethodSummary.ClassId classId) { + try { + Class clazz = loader.forName(classId.className); + return metaAccess.lookupJavaType(clazz); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + return null; + } catch (UnsupportedFeatureException e) { + e.printStackTrace(); + return null; + } + } + + @Override + public AnalysisMethod resolveMethod(AnalysisType clazz, SerializableMethodSummary.MethodId methodId) { + for (AnalysisMethod method : clazz.getDeclaredMethods()) { + if (getId(method).equals(methodId)) { + return method; + } + } + for (AnalysisMethod ctor : clazz.getDeclaredConstructors()) { + if (getId(ctor).equals(methodId)) { + return ctor; + } + } + return null; + } + + @Override + public AnalysisMethod resolveMethod(SerializableMethodSummary.MethodId methodId) { + AnalysisType clazz = resolveClass(methodId.classId); + if (clazz == null) { + return null; + } + return resolveMethod(clazz, methodId); + } + + @Override + public AnalysisField resolveField(AnalysisType clazz, SerializableMethodSummary.FieldId fieldId) { + for (AnalysisField instanceField : clazz.getInstanceFields(false)) { + if (getId(instanceField).equals(fieldId)) { + return instanceField; + } + } + for (AnalysisField staticField : clazz.getStaticFields()) { + if (getId(staticField).equals(fieldId)) { + return staticField; + } + } + return null; + } + + @Override + public AnalysisField resolveField(SerializableMethodSummary.FieldId fieldId) { + AnalysisType clazz = resolveClass(fieldId.classId); + if (clazz == null) { + return null; + } + return resolveField(clazz, fieldId); + } + + @Override + public SerializableMethodSummary.ClassId getId(AnalysisType type) { + return new SerializableMethodSummary.ClassId(type.getJavaClass().getName()); + } + + @Override + public SerializableMethodSummary.MethodId getId(AnalysisMethod method) { + return new SerializableMethodSummary.MethodId(getId(method.getDeclaringClass()), method.getQualifiedName()); + } + + @Override + public SerializableMethodSummary.FieldId getId(AnalysisField field) { + return new SerializableMethodSummary.FieldId(getId(field.getDeclaringClass()), field.getName()); + } +} From 47d41d57cdc03301ee87eedf16cbb7b2d1b508fd Mon Sep 17 00:00:00 2001 From: David Kozak Date: Tue, 23 Nov 2021 15:42:19 +0100 Subject: [PATCH 36/65] temporarily disable type initializer graph --- .../svm/hosted/classinitialization/TypeInitializerGraph.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/TypeInitializerGraph.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/TypeInitializerGraph.java index ea361d318812..bb8bc9624333 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/TypeInitializerGraph.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/TypeInitializerGraph.java @@ -118,7 +118,9 @@ private Safety initialTypeInitializerSafety(AnalysisType t) { } boolean isUnsafe(AnalysisType type) { - return types.get(type) == Safety.UNSAFE; + // todo fix + return true; + // return types.get(type) == Safety.UNSAFE; } public void setUnsafe(AnalysisType t) { From 88165c7842a5c59397c6bc190563fd845c6220aa Mon Sep 17 00:00:00 2001 From: David Kozak Date: Tue, 23 Nov 2021 15:53:16 +0100 Subject: [PATCH 37/65] fix after rebase --- .../src/com/oracle/graal/pointsto/BigBang.java | 2 ++ .../src/com/oracle/svm/hosted/NativeImageGenerator.java | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java index 32bbb43ac550..a77703e3ae17 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java @@ -41,6 +41,7 @@ import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.meta.AnalysisType.UsageKind; import com.oracle.graal.pointsto.meta.AnalysisUniverse; +import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.graal.pointsto.meta.HostedProviders; import com.oracle.graal.pointsto.util.Timer; @@ -49,6 +50,7 @@ import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.graph.NodeSourcePosition; +import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.options.OptionValues; import java.io.PrintWriter; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index f0cdea31f625..5b0c9262dea0 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -30,9 +30,9 @@ import static org.graalvm.compiler.hotspot.JVMCIVersionCheck.JVMCI8_RELEASES_URL; import static org.graalvm.compiler.replacements.StandardGraphBuilderPlugins.registerInvocationPlugins; -import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.io.PrintWriter; import java.lang.ref.Reference; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -57,12 +57,14 @@ import java.util.concurrent.ForkJoinPool; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.BooleanSupplier; +import java.util.function.Consumer; import java.util.stream.Collectors; import com.oracle.graal.pointsto.PointsToAnalysis; import com.oracle.graal.pointsto.meta.PointsToAnalysisFactory; import com.oracle.graal.pointsto.meta.PointsToAnalysisMethod; import com.oracle.graal.pointsto.infrastructure.WrappedElement; +import com.oracle.graal.pointsto.reports.ReportUtils; import com.oracle.graal.reachability.MethodSummary; import com.oracle.graal.reachability.SimpleInMemoryMethodSummaryProvider; import com.oracle.graal.reachability.summaries.MethodSummaryStorage; From b95392025a84e44900891e49ff66e4005f50e1ca Mon Sep 17 00:00:00 2001 From: David Kozak Date: Mon, 29 Nov 2021 16:22:37 +0100 Subject: [PATCH 38/65] temporarily update AMD64LinuxUContextRegisterDumper --- .../core/posix/amd64/AMD64LinuxUContextRegisterDumper.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/amd64/AMD64LinuxUContextRegisterDumper.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/amd64/AMD64LinuxUContextRegisterDumper.java index ca6a660c6bb9..bebcf0e24b6d 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/amd64/AMD64LinuxUContextRegisterDumper.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/amd64/AMD64LinuxUContextRegisterDumper.java @@ -82,14 +82,14 @@ public void dumpRegisters(Log log, ucontext_t uContext, boolean printLocationInf } @Override - @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true, calleeMustBe = false) + @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true) public PointerBase getHeapBase(ucontext_t uContext) { GregsPointer gregs = uContext.uc_mcontext_linux_amd64_gregs(); return WordFactory.pointer(gregs.read(GregEnumLinuxAMD64.REG_R14())); } @Override - @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true, calleeMustBe = false) + @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true) public PointerBase getThreadPointer(ucontext_t uContext) { GregsPointer gregs = uContext.uc_mcontext_linux_amd64_gregs(); return WordFactory.pointer(gregs.read(GregEnumLinuxAMD64.REG_R15())); From 5c9b6bf4418c1e9617ad2b0a099cd159d312a47d Mon Sep 17 00:00:00 2001 From: David Kozak Date: Wed, 1 Dec 2021 11:11:13 +0100 Subject: [PATCH 39/65] various fixes --- .../graal/pointsto/meta/AnalysisMethod.java | 3 +++ .../graal/pointsto/meta/AnalysisType.java | 15 ++++++++++++- .../graal/reachability/MethodSummary.java | 5 +++++ .../SimpleInMemoryMethodSummaryProvider.java | 11 +++++++++- .../oracle/svm/hosted/code/CompileQueue.java | 22 ++++++++++++++++--- 5 files changed, 51 insertions(+), 5 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java index 33db6bf41417..e027c1c70eb3 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java @@ -628,6 +628,9 @@ public void setReason(Object reason) { } public String getReason() { + if (reason == null) { + return "no reason - it just happened :O"; + } if (reason instanceof StackTraceElement[]) { return Arrays.toString(((StackTraceElement[]) reason)); } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java index 64355d0b696d..ef1301e92ada 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java @@ -793,7 +793,20 @@ public int getModifiers() { @Override public boolean isAssignableFrom(ResolvedJavaType other) { - AnalysisType analysisOther = other instanceof AnalysisType ? ((AnalysisType) other) : universe.lookup(other); + AnalysisType analysisOther; + if (other instanceof AnalysisType) { + analysisOther = ((AnalysisType) other); + } else if (other instanceof WrappedJavaType) { + // might be a HostedType, which is not accessible here, but implements WrappedJavaType + WrappedJavaType wrapped = (WrappedJavaType) other; + if (wrapped.getWrapped() instanceof AnalysisType) { + analysisOther = ((AnalysisType) wrapped.getWrapped()); + } else { + analysisOther = universe.lookup(other); + } + } else { + analysisOther = universe.lookup(other); + } ResolvedJavaType subst = universe.substitutions.resolve(analysisOther.wrapped); return wrapped.isAssignableFrom(subst); } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java index 5c5f2c3f5470..0ec3745c70cb 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java @@ -32,6 +32,7 @@ import org.graalvm.compiler.core.common.spi.ForeignCallSignature; import java.util.Arrays; +import java.util.List; public class MethodSummary { public static final MethodSummary EMPTY = new MethodSummary(new AnalysisMethod[0], new AnalysisMethod[0], new AnalysisType[0], new AnalysisType[0], new AnalysisField[0], new AnalysisField[0], @@ -76,6 +77,10 @@ public MethodSummary(AnalysisMethod[] invokedMethods, AnalysisMethod[] implement this.foreignCallSignatures = new ForeignCallSignature[0]; } + public static MethodSummary accessed(List accessedTypes) { + return new MethodSummary(new AnalysisMethod[0], new AnalysisMethod[0], accessedTypes.toArray(new AnalysisType[0]), new AnalysisType[0], new AnalysisField[0], new AnalysisField[0]); + } + @Override public String toString() { return "MethodSummary{" + diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java index de78b7dd6095..6fc4fad6d470 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java @@ -58,7 +58,9 @@ import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; public class SimpleInMemoryMethodSummaryProvider implements MethodSummaryProvider { @@ -75,7 +77,14 @@ public MethodSummary getSummary(BigBang bb, AnalysisMethod method) { AnalysisParsedGraph analysisParsedGraph = method.ensureGraphParsed(bb); if (analysisParsedGraph.getEncodedGraph() == null) { System.err.println("Encoded empty for " + method); - return MethodSummary.EMPTY; + List accessedTypes = new ArrayList<>(); + try { + accessedTypes = Arrays.stream(method.getParameters()).map(param -> analysisType(((ResolvedJavaType) param.getType()))).collect(Collectors.toList()); + } catch (UnsupportedOperationException ex) { + ex.printStackTrace(); + } + accessedTypes.add(analysisType((ResolvedJavaType) method.getSignature().getReturnType(null))); + return MethodSummary.accessed(accessedTypes); } StructuredGraph decoded = InlineBeforeAnalysis.decodeGraph(bb, method, analysisParsedGraph); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java index d0ddf7ada531..b58990396866 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java @@ -44,6 +44,7 @@ import java.util.concurrent.ForkJoinPool; import java.util.stream.Collectors; +import com.oracle.svm.hosted.phases.StrengthenStampsPhase; import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; @@ -172,6 +173,8 @@ import com.oracle.svm.hosted.phases.ImageBuildStatisticsCounterPhase; import com.oracle.svm.hosted.phases.ImplicitAssertionsPhase; import com.oracle.svm.hosted.phases.StrengthenStampsPhase; +import com.oracle.svm.hosted.reporting.ProgressReporter; +import com.oracle.svm.hosted.reporting.ProgressReporter.ReporterClosable; import com.oracle.svm.hosted.substitute.DeletedMethod; import com.oracle.svm.util.ImageBuildStatistics; @@ -380,7 +383,6 @@ public CompileQueue(DebugContext debug, FeatureHandler featureHandler, HostedUni this.executor = new CompletionExecutor(universe.getBigBang(), executorService, universe.getBigBang().getHeartbeatCallback()); this.featureHandler = featureHandler; this.snippetReflection = snippetReflection; - callForReplacements(debug, runtimeConfig); } @@ -459,7 +461,9 @@ protected PhaseSuite afterParseCanonicalization() { phaseSuite.appendPhase(new DeadStoreRemovalPhase()); phaseSuite.appendPhase(new DevirtualizeCallsPhase()); phaseSuite.appendPhase(CanonicalizerPhase.create()); -// phaseSuite.appendPhase(new StrengthenStampsPhase()); + if (!NativeImageOptions.UseExperimentalReachabilityAnalysis.getValue()) { + phaseSuite.appendPhase(new StrengthenStampsPhase()); + } phaseSuite.appendPhase(CanonicalizerPhase.create()); phaseSuite.appendPhase(new OptimizeExceptionPathsPhase()); if (ImageBuildStatistics.Options.CollectImageBuildStatistics.getValue(universe.hostVM().options())) { @@ -797,7 +801,13 @@ private StructuredGraph transplantGraph(DebugContext debug, HostedMethod hMethod AnalysisMethod aMethod = hMethod.getWrapped(); StructuredGraph aGraph = aMethod.getAnalyzedGraph(); if (aGraph == null) { - throw VMError.shouldNotReachHere("Method not parsed during static analysis: " + aMethod.format("%r %H.%n(%p)") + ". Reachable from: " + reason); + // todo (d-kozak) how to handle this properly? (spring boot case, where method.getCode() + // is null) + HostedProviders providers = universe.getBigBang().getProviders(); + String msg = "Method not parsed during static analysis: " + aMethod.format("%r %H.%n(%p)") + ". Reachable from: " + reason; + System.err.println(msg); + aGraph = DeletedMethod.buildGraph(debug, hMethod, providers, msg); +// throw VMError.shouldNotReachHere(msg); } /* @@ -1036,6 +1046,12 @@ private void defaultParseFunction(DebugContext debug, HostedMethod method, Compi ". Make sure you have used Graal annotation processors on the parent-project of the method's declaring class."); } + if (method.getQualifiedName().startsWith("org.springframework.transaction.reactive.TransactionalOperator.create(")) { + // todo(d-kozak) get rid of this + System.err.println("!!!!!! Skipping org.springframework.transaction.reactive.TransactionalOperator.create("); + return; + } + HostedProviders providers = (HostedProviders) config.lookupBackend(method).getProviders(); boolean needParsing = false; From 501990bddf5535e2d68f2519e09c430db655a74c Mon Sep 17 00:00:00 2001 From: David Kozak Date: Wed, 1 Dec 2021 11:15:47 +0100 Subject: [PATCH 40/65] style fixes --- .../SerializableMethodSummary.java | 22 +++++++++++++++---- .../summaries/DummyHashingStrategy.java | 2 +- .../reachability/summaries/MethodHash.java | 1 + .../summaries/MethodSummaryStorage.java | 4 +++- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SerializableMethodSummary.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SerializableMethodSummary.java index b596ecc27b58..6d160df85876 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SerializableMethodSummary.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SerializableMethodSummary.java @@ -32,6 +32,8 @@ public class SerializableMethodSummary implements Serializable { + private static final long serialVersionUID = 1L; + public SerializableMethodSummary(MethodHash hash, MethodId[] invokedMethods, MethodId[] implementationInvokedMethods, ClassId[] accessedTypes, ClassId[] instantiatedTypes, FieldId[] readFields, FieldId[] writtenFields) { this.hash = hash; @@ -44,6 +46,9 @@ public SerializableMethodSummary(MethodHash hash, MethodId[] invokedMethods, Met } public static class ClassId implements Serializable { + + private static final long serialVersionUID = 1L; + public final String className; public ClassId(String className) { @@ -76,6 +81,9 @@ public String toString() { } public static class MethodId implements Serializable { + + private static final long serialVersionUID = 1L; + public final ClassId classId; public final String methodName; @@ -86,10 +94,12 @@ public MethodId(ClassId classId, String methodName) { @Override public boolean equals(Object o) { - if (this == o) + if (this == o) { return true; - if (o == null || getClass() != o.getClass()) + } + if (o == null || getClass() != o.getClass()) { return false; + } MethodId methodId = (MethodId) o; return Objects.equals(classId, methodId.classId) && Objects.equals(methodName, methodId.methodName); } @@ -109,6 +119,8 @@ public String toString() { } public static class FieldId implements Serializable { + private static final long serialVersionUID = 1L; + public final ClassId classId; public final String fieldName; @@ -119,10 +131,12 @@ public FieldId(ClassId classId, String fieldName) { @Override public boolean equals(Object o) { - if (this == o) + if (this == o) { return true; - if (o == null || getClass() != o.getClass()) + } + if (o == null || getClass() != o.getClass()) { return false; + } FieldId fieldId = (FieldId) o; return Objects.equals(classId, fieldId.classId) && Objects.equals(fieldName, fieldId.fieldName); } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/DummyHashingStrategy.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/DummyHashingStrategy.java index 5f58e530ed56..e151aab5da46 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/DummyHashingStrategy.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/DummyHashingStrategy.java @@ -42,7 +42,7 @@ public boolean isValid(AnalysisMethod method, SerializableMethodSummary summary) return summary.hash.getValue() == getHash(method); } - private long getHash(AnalysisMethod method) { + private static long getHash(AnalysisMethod method) { return Arrays.hashCode(method.getCode()); } } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/MethodHash.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/MethodHash.java index 25634c00d9e8..9d34022e7869 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/MethodHash.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/MethodHash.java @@ -27,6 +27,7 @@ import java.io.Serializable; public final class MethodHash implements Serializable { + private static final long serialVersionUID = 1L; private final long value; diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/MethodSummaryStorage.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/MethodSummaryStorage.java index 636f32cc32ac..639bc3ef872c 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/MethodSummaryStorage.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/summaries/MethodSummaryStorage.java @@ -94,6 +94,7 @@ public void loadData() { return; } try (ObjectInputStream stream = new ObjectInputStream(new FileInputStream(summaryFileName))) { + @SuppressWarnings("unchecked") Map summaries = (Map) stream.readObject(); processSummaryFile(summaries); } catch (IOException | ClassNotFoundException e) { @@ -134,6 +135,7 @@ private MethodSummary resolveSummary(SerializableMethodSummary value) { } public Type[] resolveHelper(SerializedType[] inputArray, Function resolver, Class typeTag) { + @SuppressWarnings("unchecked") Type[] res = (Type[]) Array.newInstance(typeTag, inputArray.length); for (int i = 0; i < inputArray.length; i++) { SerializedType elem = inputArray[i]; @@ -183,7 +185,7 @@ private SerializableMethodSummary serializeSummary(PersistedSummary persistedSum return new SerializableMethodSummary(persistedSummary.getHash(), invokedMethods, implInvokedMethods, accessedTypes, instantiatedTypes, readFields, writtenFields); } - private boolean canSerialize(PersistedSummary persistedSummary) { + private static boolean canSerialize(PersistedSummary persistedSummary) { MethodSummary summary = persistedSummary.getSummary(); // todo implement return true; From 6c8c0e9e66f8fda2f8cc6cb1816bed10906a8a6e Mon Sep 17 00:00:00 2001 From: David Kozak Date: Thu, 2 Dec 2021 15:43:59 +0100 Subject: [PATCH 41/65] temporal logging --- .../svm/core/graal/snippets/SubstrateAllocationSnippets.java | 1 + .../src/com/oracle/svm/hosted/meta/UniverseBuilder.java | 1 + 2 files changed, 2 insertions(+) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java index 776e25bd3f54..5dd00374cb66 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java @@ -655,6 +655,7 @@ public void lower(ValidateNewInstanceClassNode node, LoweringTool tool) { * {@link MetaAccessExtensionProvider#canConstantFoldDynamicAllocation} returns false. */ public static DynamicHub ensureMarkedAsInstantiated(DynamicHub hub) { + System.out.println("here here here " + hub); if (!hub.isInstantiated()) { throw VMError.shouldNotReachHere("Cannot allocate type that is not marked as instantiated: " + hub.getName()); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java index e16774c5e195..09af61da2ad9 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java @@ -939,6 +939,7 @@ private void buildHubs() { DynamicHub hub = type.getHub(); hub.setData(layoutHelper, type.getTypeID(), monitorOffset, type.getTypeCheckStart(), type.getTypeCheckRange(), type.getTypeCheckSlot(), type.getTypeCheckSlots(), vtable, referenceMapIndex, type.isInstantiated()); + System.out.println(hub + " instantiated: " + type.isInstantiated()); } } From 36900bcd618d4c5cbf1beeffd18c8143477cf8af Mon Sep 17 00:00:00 2001 From: David Kozak Date: Thu, 2 Dec 2021 16:35:48 +0100 Subject: [PATCH 42/65] temporal extra loop in the analysis --- .../reachability/ReachabilityAnalysis.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index 98bfeb52aea4..0db039ced023 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -279,15 +279,18 @@ public boolean finish() throws InterruptedException { universe.setAnalysisDataValid(false); int numTypes; - do { - runReachability(); + for (int i = 0; i < 10; i++) { + do { + runReachability(); - assert executor.getPostedOperations() == 0; - numTypes = universe.getTypes().size(); + assert executor.getPostedOperations() == 0; + numTypes = universe.getTypes().size(); - checkObjectGraph(); + checkObjectGraph(); - } while (executor.getPostedOperations() != 0 || numTypes != universe.getTypes().size()); + } while (executor.getPostedOperations() != 0 || numTypes != universe.getTypes().size()); + + } universe.setAnalysisDataValid(true); @@ -365,7 +368,7 @@ private void checkObjectGraph() throws InterruptedException { objectScanner.scanBootImageHeapRoots(null, null); executor.complete(); executor.shutdown(); - executor.init(null); + executor.init(timing); } else { objectScanner.scanBootImageHeapRoots(null, null); } From 5f161ec59d497e44ba181e285464c90128ad70d2 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Thu, 2 Dec 2021 17:48:53 +0100 Subject: [PATCH 43/65] dump stats --- .../com/oracle/svm/hosted/NativeImageGenerator.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index 5b0c9262dea0..e16f17ca6d04 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -560,6 +560,8 @@ private void doRun(Map entryPoints, return; } + dump(imageName, aUniverse); + // dumpAnalysisStats(); NativeImageHeap heap; @@ -718,6 +720,14 @@ private void doRun(Map entryPoints, } } + private void dump(String bigbang, AnalysisUniverse aUniverse) { + long types = aUniverse.getTypes().stream().filter(AnalysisType::isReachable).count(); + long instantiatedTypes = aUniverse.getTypes().stream().filter(AnalysisType::isInstantiated).count(); + long invokedMethods = aUniverse.getMethods().stream().filter(AnalysisMethod::isInvoked).count(); + long implInvokedMethods = aUniverse.getMethods().stream().filter(AnalysisMethod::isImplementationInvoked).count(); + System.out.println("!!!!!" + bigbang + " types:" + instantiatedTypes + " / " + types + ", methods: " + invokedMethods + " / " + implInvokedMethods); + } + private static final String DUMP_FOLDER = "/Users/dkozak/tmp/hello-dir/stats/"; private static final String METHOD_FORMAT = "%H.%n(%P)"; @@ -733,7 +743,7 @@ private void dumpAnalysisStats() { String prefix = analysisPrefix(); List, String>> pairs = Arrays.asList(Pair.create(reachableTypes, "types"), Pair.create(invokedMethods, "invokedMethods"), - Pair.create(implInvokedMethods, "implInvokedMethods")); + Pair.create(implInvokedMethods, "implInvokedMethods")); for (Pair, String> pair : pairs) { try (FileWriter writer = new FileWriter(DUMP_FOLDER + prefix + pair.getRight())) { From 3a5df67a94a2f5c05621317e68a31eadf7c4da86 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Fri, 3 Dec 2021 12:47:44 +0100 Subject: [PATCH 44/65] remove debug dumps --- .../com/oracle/graal/reachability/ReachabilityAnalysis.java | 3 --- .../svm/core/graal/snippets/SubstrateAllocationSnippets.java | 1 - .../src/com/oracle/svm/hosted/meta/UniverseBuilder.java | 1 - 3 files changed, 5 deletions(-) diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index 0db039ced023..1e243dfd91f1 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -279,7 +279,6 @@ public boolean finish() throws InterruptedException { universe.setAnalysisDataValid(false); int numTypes; - for (int i = 0; i < 10; i++) { do { runReachability(); @@ -290,8 +289,6 @@ public boolean finish() throws InterruptedException { } while (executor.getPostedOperations() != 0 || numTypes != universe.getTypes().size()); - } - universe.setAnalysisDataValid(true); return true; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java index 5dd00374cb66..776e25bd3f54 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java @@ -655,7 +655,6 @@ public void lower(ValidateNewInstanceClassNode node, LoweringTool tool) { * {@link MetaAccessExtensionProvider#canConstantFoldDynamicAllocation} returns false. */ public static DynamicHub ensureMarkedAsInstantiated(DynamicHub hub) { - System.out.println("here here here " + hub); if (!hub.isInstantiated()) { throw VMError.shouldNotReachHere("Cannot allocate type that is not marked as instantiated: " + hub.getName()); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java index 09af61da2ad9..e16774c5e195 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java @@ -939,7 +939,6 @@ private void buildHubs() { DynamicHub hub = type.getHub(); hub.setData(layoutHelper, type.getTypeID(), monitorOffset, type.getTypeCheckStart(), type.getTypeCheckRange(), type.getTypeCheckSlot(), type.getTypeCheckSlots(), vtable, referenceMapIndex, type.isInstantiated()); - System.out.println(hub + " instantiated: " + type.isInstantiated()); } } From 98f49fdf0d63dc39822a7a7eb96143cd20b8d769 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Fri, 3 Dec 2021 13:02:09 +0100 Subject: [PATCH 45/65] try reducing max number of threads to 4 --- .../src/com/oracle/svm/hosted/NativeImageOptions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java index beef95d881f8..ea5e34626e39 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java @@ -147,7 +147,7 @@ public static CStandards getCStandard() { * Configures the number of threads used by the {@link CompletionExecutor}. */ @Option(help = "The maximum number of threads to use concurrently during native image generation.")// - public static final HostedOptionKey NumberOfThreads = new HostedOptionKey<>(Math.min(Runtime.getRuntime().availableProcessors(), 32)); + public static final HostedOptionKey NumberOfThreads = new HostedOptionKey<>(Math.min(Runtime.getRuntime().availableProcessors(), 4)); /* * Analysis scales well up to 12 cores and gives slight improvements until 18 cores. We set the From abf985c530fc263c6a4fa47c3a7287a416516703 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Fri, 3 Dec 2021 13:45:31 +0100 Subject: [PATCH 46/65] try reducing max number of threads to 1 --- .../src/com/oracle/svm/hosted/NativeImageOptions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java index ea5e34626e39..cc560cc9724d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java @@ -147,7 +147,7 @@ public static CStandards getCStandard() { * Configures the number of threads used by the {@link CompletionExecutor}. */ @Option(help = "The maximum number of threads to use concurrently during native image generation.")// - public static final HostedOptionKey NumberOfThreads = new HostedOptionKey<>(Math.min(Runtime.getRuntime().availableProcessors(), 4)); + public static final HostedOptionKey NumberOfThreads = new HostedOptionKey<>(Math.min(Runtime.getRuntime().availableProcessors(), 1)); /* * Analysis scales well up to 12 cores and gives slight improvements until 18 cores. We set the From d5c0712d5dee1ca001bda7da53d9baa2c87aa26c Mon Sep 17 00:00:00 2001 From: David Kozak Date: Fri, 3 Dec 2021 14:28:39 +0100 Subject: [PATCH 47/65] try not throwing the exception in SubstrateAllocationSnippets --- .../svm/core/graal/snippets/SubstrateAllocationSnippets.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java index 776e25bd3f54..e642c8399cf8 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java @@ -656,7 +656,9 @@ public void lower(ValidateNewInstanceClassNode node, LoweringTool tool) { */ public static DynamicHub ensureMarkedAsInstantiated(DynamicHub hub) { if (!hub.isInstantiated()) { - throw VMError.shouldNotReachHere("Cannot allocate type that is not marked as instantiated: " + hub.getName()); + System.err.println("Cannot allocate type that is not marked as instantiated: " + hub.getName()); +// throw VMError.shouldNotReachHere("Cannot allocate type that is not marked as instantiated: " + +// hub.getName()); } return hub; } From c5d6d3643dfd2011a4a24715c735e43943763c78 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Fri, 3 Dec 2021 15:49:58 +0100 Subject: [PATCH 48/65] dump summary info --- .../graal/reachability/MethodSummary.java | 23 +++++++++++++++++++ .../reachability/ReachabilityAnalysis.java | 18 ++++++++++----- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java index 0ec3745c70cb..20f945fd26a8 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummary.java @@ -77,6 +77,29 @@ public MethodSummary(AnalysisMethod[] invokedMethods, AnalysisMethod[] implement this.foreignCallSignatures = new ForeignCallSignature[0]; } + public String textSummary() { + StringBuilder builder = new StringBuilder(); + return builder.append("invoked: ") + .append(invokedMethods.length) + .append(", impl invoked: ") + .append(implementationInvokedMethods.length) + .append(", accessed: ") + .append(accessedTypes.length) + .append(", instantiated: ") + .append(instantiatedTypes.length) + .append(", read: ") + .append(readFields.length) + .append(", written: ") + .append(writtenFields.length) + .append(", embedded: ") + .append(embeddedConstants.length) + .append(", desc: ") + .append(foreignCallDescriptors.length) + .append(", sign: ") + .append(foreignCallSignatures.length) + .toString(); + } + public static MethodSummary accessed(List accessedTypes) { return new MethodSummary(new AnalysisMethod[0], new AnalysisMethod[0], accessedTypes.toArray(new AnalysisType[0]), new AnalysisType[0], new AnalysisField[0], new AnalysisField[0]); } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index 1e243dfd91f1..428aba821aa1 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -149,6 +149,7 @@ private void onMethodImplementationInvoked(AnalysisMethod method) { try (Timer.StopTimer t = summaryTimer.start()) { summary = methodSummaryProvider.getSummary(this, method); } + dumpSummary(method, summary); processSummary(method, summary); summaries.put(method, summary); } catch (Throwable ex) { @@ -279,15 +280,15 @@ public boolean finish() throws InterruptedException { universe.setAnalysisDataValid(false); int numTypes; - do { - runReachability(); + do { + runReachability(); - assert executor.getPostedOperations() == 0; - numTypes = universe.getTypes().size(); + assert executor.getPostedOperations() == 0; + numTypes = universe.getTypes().size(); - checkObjectGraph(); + checkObjectGraph(); - } while (executor.getPostedOperations() != 0 || numTypes != universe.getTypes().size()); + } while (executor.getPostedOperations() != 0 || numTypes != universe.getTypes().size()); universe.setAnalysisDataValid(true); @@ -402,6 +403,7 @@ public void processGraph(StructuredGraph graph) { summary = methodSummaryProvider.getSummary(this, graph); } AnalysisMethod method = analysisMethod(graph.method()); + dumpSummary(method, summary); method.registerAsInvoked(null); method.registerAsImplementationInvoked(null); processSummary(method, summary.withoutMethods()); @@ -409,6 +411,10 @@ public void processGraph(StructuredGraph graph) { registerForeignCalls(graph); } + private void dumpSummary(AnalysisMethod method, MethodSummary summary) { + System.out.println("summary: " + method.getQualifiedName() + " " + summary.textSummary()); + } + private void registerForeignCalls(StructuredGraph graph) { for (Node n : graph.getNodes()) { if (n instanceof ForeignCall) { From d8b8f0efaec9e9f5634a37897d9ff17f0834d6a5 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Fri, 3 Dec 2021 16:33:50 +0100 Subject: [PATCH 49/65] only dump one method --- .../com/oracle/graal/reachability/ReachabilityAnalysis.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index 428aba821aa1..e0998998f656 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -412,7 +412,9 @@ public void processGraph(StructuredGraph graph) { } private void dumpSummary(AnalysisMethod method, MethodSummary summary) { - System.out.println("summary: " + method.getQualifiedName() + " " + summary.textSummary()); + if (method.getQualifiedName().equals("java.util.Collections.newSetFromMap(java.util.Map)")) { + System.out.println("summary: " + method.getQualifiedName() + " " + summary.textSummary()); + } } private void registerForeignCalls(StructuredGraph graph) { From a24b4add37a352641412a677ec596be267f04e97 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Sat, 4 Dec 2021 11:10:58 +0100 Subject: [PATCH 50/65] only dump one method - but with nodes --- .../SimpleInMemoryMethodSummaryProvider.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java index 6fc4fad6d470..b72a7ceb44da 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java @@ -60,6 +60,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Random; import java.util.stream.Collectors; public class SimpleInMemoryMethodSummaryProvider implements MethodSummaryProvider { @@ -132,6 +133,7 @@ protected class Instance { public final List foreignCallSignatures = new ArrayList<>(); private MethodSummary createSummaryFromGraph(StructuredGraph graph) { + dump(graph); for (Node n : graph.getNodes()) { if (n instanceof NewInstanceNode) { @@ -213,5 +215,18 @@ private MethodSummary createSummaryFromGraph(StructuredGraph graph) { instantiatedTypes.toArray(new AnalysisType[0]), readFields.toArray(new AnalysisField[0]), writtenFields.toArray(new AnalysisField[0]), embeddedConstants.toArray(new JavaConstant[0]), foreignCallDescriptors.toArray(new ForeignCallDescriptor[0]), foreignCallSignatures.toArray(new ForeignCallSignature[0])); } + + private void dump(StructuredGraph graph) { + if (!((AnalysisMethod) graph.method()).getQualifiedName().equals("java.util.Collections.newSetFromMap(java.util.Map)")) { + return; + } + Random rnd = new Random(); + int id = rnd.nextInt(); + System.out.println("====="); + for (Node node : graph.getNodes()) { + System.out.println(id + " " + node); + } + System.out.println("====="); + } } } From 21f927db0cb0f5e88d29dad95380cdf9706bedb4 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Sat, 4 Dec 2021 11:29:23 +0100 Subject: [PATCH 51/65] handle virtual instance and array nodes --- .../SimpleInMemoryMethodSummaryProvider.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java index b72a7ceb44da..b2f3f3c9bf90 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java @@ -53,6 +53,8 @@ import org.graalvm.compiler.nodes.java.NewInstanceNode; import org.graalvm.compiler.nodes.java.NewMultiArrayNode; import org.graalvm.compiler.nodes.java.StoreFieldNode; +import org.graalvm.compiler.nodes.virtual.VirtualArrayNode; +import org.graalvm.compiler.nodes.virtual.VirtualInstanceNode; import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode; import org.graalvm.compiler.replacements.nodes.MacroInvokable; import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode; @@ -149,6 +151,16 @@ private MethodSummary createSummaryFromGraph(StructuredGraph graph) { instantiatedTypes.add(analysisType(type)); type = type.getComponentType(); } + } else if (n instanceof VirtualInstanceNode) { + VirtualInstanceNode node = (VirtualInstanceNode) n; + instantiatedTypes.add(analysisType(node.type())); + for (ResolvedJavaField field : node.getFields()) { + readFields.add(analysisField(field)); + writtenFields.add(analysisField(field)); + } + } else if (n instanceof VirtualArrayNode) { + VirtualArrayNode node = (VirtualArrayNode) n; + instantiatedTypes.add(analysisType(node.componentType()).getArrayClass()); } else if (n instanceof ConstantNode) { ConstantNode node = (ConstantNode) n; if (!(node.getValue() instanceof JavaConstant)) { From f9e744ccefc337d4d6d8a7138abc0d2dbe594188 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Sat, 4 Dec 2021 12:39:13 +0100 Subject: [PATCH 52/65] do not include virtual fields in summaries --- .../reachability/SimpleInMemoryMethodSummaryProvider.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java index b2f3f3c9bf90..bbdb352823a8 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java @@ -154,10 +154,10 @@ private MethodSummary createSummaryFromGraph(StructuredGraph graph) { } else if (n instanceof VirtualInstanceNode) { VirtualInstanceNode node = (VirtualInstanceNode) n; instantiatedTypes.add(analysisType(node.type())); - for (ResolvedJavaField field : node.getFields()) { - readFields.add(analysisField(field)); - writtenFields.add(analysisField(field)); - } +// for (ResolvedJavaField field : node.getFields()) { +// readFields.add(analysisField(field)); +// writtenFields.add(analysisField(field)); +// } } else if (n instanceof VirtualArrayNode) { VirtualArrayNode node = (VirtualArrayNode) n; instantiatedTypes.add(analysisType(node.componentType()).getArrayClass()); From 8e5f2a2a895b18a54d666782f3f98ef855f09c0c Mon Sep 17 00:00:00 2001 From: David Kozak Date: Sat, 4 Dec 2021 19:22:18 +0100 Subject: [PATCH 53/65] remove no longer necessary debug output --- .../graal/reachability/ReachabilityAnalysis.java | 8 -------- .../SimpleInMemoryMethodSummaryProvider.java | 16 ---------------- 2 files changed, 24 deletions(-) diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index e0998998f656..7a78085fcf85 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -149,7 +149,6 @@ private void onMethodImplementationInvoked(AnalysisMethod method) { try (Timer.StopTimer t = summaryTimer.start()) { summary = methodSummaryProvider.getSummary(this, method); } - dumpSummary(method, summary); processSummary(method, summary); summaries.put(method, summary); } catch (Throwable ex) { @@ -403,7 +402,6 @@ public void processGraph(StructuredGraph graph) { summary = methodSummaryProvider.getSummary(this, graph); } AnalysisMethod method = analysisMethod(graph.method()); - dumpSummary(method, summary); method.registerAsInvoked(null); method.registerAsImplementationInvoked(null); processSummary(method, summary.withoutMethods()); @@ -411,12 +409,6 @@ public void processGraph(StructuredGraph graph) { registerForeignCalls(graph); } - private void dumpSummary(AnalysisMethod method, MethodSummary summary) { - if (method.getQualifiedName().equals("java.util.Collections.newSetFromMap(java.util.Map)")) { - System.out.println("summary: " + method.getQualifiedName() + " " + summary.textSummary()); - } - } - private void registerForeignCalls(StructuredGraph graph) { for (Node n : graph.getNodes()) { if (n instanceof ForeignCall) { diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java index bbdb352823a8..4656064cd2eb 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/SimpleInMemoryMethodSummaryProvider.java @@ -62,7 +62,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Random; import java.util.stream.Collectors; public class SimpleInMemoryMethodSummaryProvider implements MethodSummaryProvider { @@ -135,8 +134,6 @@ protected class Instance { public final List foreignCallSignatures = new ArrayList<>(); private MethodSummary createSummaryFromGraph(StructuredGraph graph) { - dump(graph); - for (Node n : graph.getNodes()) { if (n instanceof NewInstanceNode) { NewInstanceNode node = (NewInstanceNode) n; @@ -227,18 +224,5 @@ private MethodSummary createSummaryFromGraph(StructuredGraph graph) { instantiatedTypes.toArray(new AnalysisType[0]), readFields.toArray(new AnalysisField[0]), writtenFields.toArray(new AnalysisField[0]), embeddedConstants.toArray(new JavaConstant[0]), foreignCallDescriptors.toArray(new ForeignCallDescriptor[0]), foreignCallSignatures.toArray(new ForeignCallSignature[0])); } - - private void dump(StructuredGraph graph) { - if (!((AnalysisMethod) graph.method()).getQualifiedName().equals("java.util.Collections.newSetFromMap(java.util.Map)")) { - return; - } - Random rnd = new Random(); - int id = rnd.nextInt(); - System.out.println("====="); - for (Node node : graph.getNodes()) { - System.out.println(id + " " + node); - } - System.out.println("====="); - } } } From 5edeeac8d98e91e287bbb34b67b2d36da70d069a Mon Sep 17 00:00:00 2001 From: David Kozak Date: Sat, 4 Dec 2021 19:35:44 +0100 Subject: [PATCH 54/65] temporarily allow com.oracle.svm.core.graal.snippets.DeoptHostedSnippets --- .../src/com/oracle/svm/hosted/NativeImageGenerator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index e16f17ca6d04..99265aa46623 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -1731,7 +1731,8 @@ private void checkName(String name, AnalysisMethod method) { * they are JDK internal types. */ String lname = name.toLowerCase(); - if (lname.contains("hosted")) { + // todo resolve (d-kozak) + if (lname.contains("hosted") && !lname.startsWith("com.oracle.svm.core.graal.snippets.deopthostedsnippets")) { bb.getUnsupportedFeatures().addMessage(name, method, "Hosted element used at run time: " + name); } else if (SubstrateUtil.isBuildingLibgraal() && (!name.startsWith("jdk.internal")) && (lname.contains("hotspot"))) { bb.getUnsupportedFeatures().addMessage(name, method, "HotSpot element used at run time: " + name); From c1faf709b29dbc1a52cb6e06acd4ec95dd0df00a Mon Sep 17 00:00:00 2001 From: David Kozak Date: Sat, 4 Dec 2021 19:52:12 +0100 Subject: [PATCH 55/65] add missing uninterruptible annotation --- .../src/com/oracle/svm/core/jfr/JfrUnlockedChunkWriter.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrUnlockedChunkWriter.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrUnlockedChunkWriter.java index e31b42626f88..b49bc178a969 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrUnlockedChunkWriter.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrUnlockedChunkWriter.java @@ -24,6 +24,8 @@ */ package com.oracle.svm.core.jfr; +import com.oracle.svm.core.annotate.Uninterruptible; + /** * An interface that collects all {@link JfrChunkWriter} methods that may be called without holding * a lock. @@ -44,5 +46,6 @@ public interface JfrUnlockedChunkWriter { * It is valid to call this method without locking but be aware that the result will be racy in * that case. */ + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) boolean hasOpenFile(); } From 5c4487925cd6332e94b2970c4bed5195a9ccdf15 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Sat, 4 Dec 2021 19:53:58 +0100 Subject: [PATCH 56/65] add missing uninterruptible annotation --- .../com/oracle/svm/core/genscavenge/RuntimeCodeCacheWalker.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/RuntimeCodeCacheWalker.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/RuntimeCodeCacheWalker.java index 2614fc375a2d..359c0628b3c1 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/RuntimeCodeCacheWalker.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/RuntimeCodeCacheWalker.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.core.genscavenge; +import com.oracle.svm.core.annotate.Uninterruptible; import org.graalvm.compiler.word.Word; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -57,6 +58,7 @@ final class RuntimeCodeCacheWalker implements CodeInfoVisitor { } @Override + @Uninterruptible(reason = "Called from uninterruptible code.") @DuplicatedInNativeCode public boolean visitCode(T codeInfo) { if (RuntimeCodeInfoAccess.areAllObjectsOnImageHeap(codeInfo)) { From 503b04a297bbe8d1f90551de2cba0485799c79f2 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Sat, 4 Dec 2021 19:58:51 +0100 Subject: [PATCH 57/65] add missing uninterruptible annotation --- .../src/com/oracle/svm/core/heap/RuntimeCodeCacheCleaner.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/RuntimeCodeCacheCleaner.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/RuntimeCodeCacheCleaner.java index 747476cecd70..15d275bff5c0 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/RuntimeCodeCacheCleaner.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/RuntimeCodeCacheCleaner.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.core.heap; +import com.oracle.svm.core.annotate.Uninterruptible; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -62,6 +63,7 @@ public RuntimeCodeCacheCleaner() { } @Override + @Uninterruptible(reason = "Called from uninterruptible code.") public boolean visitCode(T codeInfo) { if (RuntimeCodeInfoAccess.areAllObjectsOnImageHeap(codeInfo)) { return true; From 66feaf0b7785e562f0ef69f52c26980f401a5e8b Mon Sep 17 00:00:00 2001 From: David Kozak Date: Sat, 4 Dec 2021 22:24:09 +0100 Subject: [PATCH 58/65] add missing uninterruptible annotation --- .../oracle/svm/core/genscavenge/RuntimeCodeCacheWalker.java | 2 ++ .../src/com/oracle/svm/core/code/CodeInfoTable.java | 1 + .../src/com/oracle/svm/core/code/RuntimeCodeInfoAccess.java | 4 ++++ .../src/com/oracle/svm/core/heap/RuntimeCodeCacheCleaner.java | 1 + 4 files changed, 8 insertions(+) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/RuntimeCodeCacheWalker.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/RuntimeCodeCacheWalker.java index 359c0628b3c1..bc0942c65a34 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/RuntimeCodeCacheWalker.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/RuntimeCodeCacheWalker.java @@ -113,10 +113,12 @@ public boolean visitCode(T codeInfo) { return true; } + @Uninterruptible(reason = "Called from uninterruptible code.") private static boolean isReachable(Object possiblyForwardedObject) { return RuntimeCodeCacheReachabilityAnalyzer.isReachable(Word.objectToUntrackedPointer(possiblyForwardedObject)); } + @Uninterruptible(reason = "Called from uninterruptible code.") private boolean hasWeakReferenceToUnreachableObject(CodeInfo codeInfo) { checkForUnreachableObjectsVisitor.initialize(); RuntimeCodeInfoAccess.walkWeakReferences(codeInfo, checkForUnreachableObjectsVisitor); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoTable.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoTable.java index 0dd70333fd63..b991967ede62 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoTable.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoTable.java @@ -226,6 +226,7 @@ private static void invalidateCodeAtSafepoint(CodeInfo info) { } @RestrictHeapAccess(access = Access.NO_ALLOCATION, reason = "Called by the GC") + @Uninterruptible(reason = "Called from uninterruptible code.") public static void invalidateNonStackCodeAtSafepoint(CodeInfo info) { VMOperation.guaranteeGCInProgress("Must only be called during a GC."); RuntimeCodeCache codeCache = getRuntimeCodeCache(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeCodeInfoAccess.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeCodeInfoAccess.java index 895a4e7efe89..87623286597f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeCodeInfoAccess.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeCodeInfoAccess.java @@ -146,6 +146,7 @@ public static Object[] prepareHeapObjectData(CodeInfoTether tether, String name, return objectFields; } + @Uninterruptible(reason = "Called from uninterruptible code.") public static boolean areAllObjectsOnImageHeap(CodeInfo info) { return cast(info).getAllObjectsAreInImageHeap(); } @@ -153,6 +154,7 @@ public static boolean areAllObjectsOnImageHeap(CodeInfo info) { /** * Walks all strong references in a {@link CodeInfo} object. */ + @Uninterruptible(reason = "Called from uninterruptible code.") public static boolean walkStrongReferences(CodeInfo info, ObjectReferenceVisitor visitor) { return NonmovableArrays.walkUnmanagedObjectArray(cast(info).getObjectFields(), visitor, CodeInfoImpl.FIRST_STRONGLY_REFERENCED_OBJFIELD, CodeInfoImpl.STRONGLY_REFERENCED_OBJFIELD_COUNT); } @@ -161,6 +163,7 @@ public static boolean walkStrongReferences(CodeInfo info, ObjectReferenceVisitor * Walks all weak references in a {@link CodeInfo} object. */ @DuplicatedInNativeCode + @Uninterruptible(reason = "Called from uninterruptible code.") public static boolean walkWeakReferences(CodeInfo info, ObjectReferenceVisitor visitor) { CodeInfoImpl impl = cast(info); boolean continueVisiting = true; @@ -181,6 +184,7 @@ public static boolean walkWeakReferences(CodeInfo info, ObjectReferenceVisitor v * This method only visits a very specific subset of all the references, so you typically want * to use {@link #walkStrongReferences} and/or {@link #walkWeakReferences} instead. */ + @Uninterruptible(reason = "Called from uninterruptible code.") public static boolean walkObjectFields(CodeInfo info, ObjectReferenceVisitor visitor) { return NonmovableArrays.walkUnmanagedObjectArray(cast(info).getObjectFields(), visitor); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/RuntimeCodeCacheCleaner.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/RuntimeCodeCacheCleaner.java index 15d275bff5c0..03e155b5abcc 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/RuntimeCodeCacheCleaner.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/RuntimeCodeCacheCleaner.java @@ -81,6 +81,7 @@ public boolean visitCode(T codeInfo) { return true; } + @Uninterruptible(reason = "Called from uninterruptible code.") private static void freeMemory(CodeInfo codeInfo) { boolean removed = RuntimeCodeInfoMemory.singleton().removeDuringGC(codeInfo); assert removed : "must have been present"; From 4beade60779b8b637c6f4fb64c4cc1d8fab86448 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Sat, 4 Dec 2021 22:24:28 +0100 Subject: [PATCH 59/65] re-enable multiple threads --- .../src/com/oracle/svm/hosted/NativeImageOptions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java index cc560cc9724d..beef95d881f8 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java @@ -147,7 +147,7 @@ public static CStandards getCStandard() { * Configures the number of threads used by the {@link CompletionExecutor}. */ @Option(help = "The maximum number of threads to use concurrently during native image generation.")// - public static final HostedOptionKey NumberOfThreads = new HostedOptionKey<>(Math.min(Runtime.getRuntime().availableProcessors(), 1)); + public static final HostedOptionKey NumberOfThreads = new HostedOptionKey<>(Math.min(Runtime.getRuntime().availableProcessors(), 32)); /* * Analysis scales well up to 12 cores and gives slight improvements until 18 cores. We set the From ee19fac0eb3cec5d9b3aae33017e7eb5a901d37f Mon Sep 17 00:00:00 2001 From: David Kozak Date: Sun, 5 Dec 2021 11:06:32 +0100 Subject: [PATCH 60/65] fixes after rebase --- .../com/oracle/graal/pointsto/PointsToAnalysis.java | 2 +- .../graal/reachability/ReachabilityAnalysis.java | 10 +++++----- .../com/oracle/svm/hosted/NativeImageGenerator.java | 3 +-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java index 8d85ee427f7e..a01a7bf4d26a 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java @@ -654,7 +654,7 @@ public void markFieldAccessed(AnalysisField field) { @Override public void markMethodImplementationInvoked(AnalysisMethod method, Object reason) { - addRootMethod(method).registerAsImplementationInvoked(null); + addRootMethod(method).registerAsImplementationInvoked(); } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index 7a78085fcf85..2e8206ce1146 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -121,7 +121,7 @@ public AnalysisMethod addRootMethod(AnalysisMethod method) { if (!method.isStatic()) { markTypeInstantiated(method.getDeclaringClass()); } - method.registerAsInvoked(null); + method.registerAsInvoked(); markMethodImplementationInvoked(method, new RuntimeException().getStackTrace()); return method; } @@ -134,7 +134,7 @@ public void markMethodImplementationInvoked(AnalysisMethod method, Object reason new RuntimeException().printStackTrace(); return; } - if (!method.registerAsImplementationInvoked(null)) { + if (!method.registerAsImplementationInvoked()) { return; } schedule(() -> onMethodImplementationInvoked(method)); @@ -250,7 +250,7 @@ public void markTypeInstantiated(AnalysisType type) { } private void markMethodInvoked(AnalysisMethod method) { - if (!method.registerAsInvoked(null)) { + if (!method.registerAsInvoked()) { return; } schedule(() -> onMethodInvoked(method)); @@ -402,8 +402,8 @@ public void processGraph(StructuredGraph graph) { summary = methodSummaryProvider.getSummary(this, graph); } AnalysisMethod method = analysisMethod(graph.method()); - method.registerAsInvoked(null); - method.registerAsImplementationInvoked(null); + method.registerAsInvoked(); + method.registerAsImplementationInvoked(); processSummary(method, summary.withoutMethods()); registerForeignCalls(graph); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index 99265aa46623..a0a8340e1a8f 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -63,7 +63,6 @@ import com.oracle.graal.pointsto.PointsToAnalysis; import com.oracle.graal.pointsto.meta.PointsToAnalysisFactory; import com.oracle.graal.pointsto.meta.PointsToAnalysisMethod; -import com.oracle.graal.pointsto.infrastructure.WrappedElement; import com.oracle.graal.pointsto.reports.ReportUtils; import com.oracle.graal.reachability.MethodSummary; import com.oracle.graal.reachability.SimpleInMemoryMethodSummaryProvider; @@ -802,7 +801,7 @@ private List getCallees(AnalysisMethod method) { @SuppressWarnings("unused") private static List getCalleesP(NativeImagePointsToAnalysis bb, AnalysisMethod method) { - return method.getTypeFlow().getInvokes().stream().flatMap(it -> it.getCallees().stream()).collect(Collectors.toList()); + return ((PointsToAnalysisMethod) method).getTypeFlow().getInvokes().stream().flatMap(it -> it.getCallees().stream()).collect(Collectors.toList()); } private static List getCalleesR(NativeImageReachabilityAnalysis bb, AnalysisMethod method) { From c0d3a98bc7c6d758b9ba8dc6a654d25fd802c4e2 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Sun, 5 Dec 2021 14:33:30 +0100 Subject: [PATCH 61/65] temporarily disable @Uninterruptible and @RestrictHeapAccess checking --- .../src/com/oracle/svm/hosted/code/CompileQueue.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java index b58990396866..79225beb3ae9 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java @@ -402,11 +402,12 @@ public void finish(DebugContext debug) { try (ProgressReporter.ReporterClosable ac = reporter.printParsing(new Timer(imageName, "(parse)"))) { parseAll(); } + // todo re-enable // Checking @Uninterruptible annotations does not take long enough to justify a timer. - new UninterruptibleAnnotationChecker(universe.getMethods()).check(); +// new UninterruptibleAnnotationChecker(universe.getMethods()).check(); // Checking @RestrictHeapAccess annotations does not take long enough to justify a // timer. - RestrictHeapAccessAnnotationChecker.check(debug, universe, universe.getMethods()); +// RestrictHeapAccessAnnotationChecker.check(debug, universe, universe.getMethods()); /* * The graph in the analysis universe is no longer necessary. This clears the graph for From ab22fe0be39c5abee39044dd5df8d6a812100f47 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Thu, 9 Dec 2021 14:54:11 +0100 Subject: [PATCH 62/65] schedule the onTypInstantiated instead of running it in the same thread --- .../com/oracle/graal/reachability/ReachabilityAnalysis.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java index 2e8206ce1146..3f0d5cebbf63 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysis.java @@ -232,6 +232,10 @@ public void markTypeInstantiated(AnalysisType type) { if (!type.registerAsAllocated(null)) { return; } + schedule(() -> onTypeInstantiated(type)); + } + + private void onTypeInstantiated(AnalysisType type) { type.forAllSuperTypes(current -> { Set invokedMethods = current.getInvokedMethods(); for (AnalysisMethod method : invokedMethods) { From 7e620df82e9801a7e298a3b558899d581786010e Mon Sep 17 00:00:00 2001 From: David Kozak Date: Thu, 9 Dec 2021 14:54:33 +0100 Subject: [PATCH 63/65] switch off the new build output --- .../src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java | 1 + .../src/com/oracle/svm/core/SubstrateOptions.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java index 23f92d063e12..8d8c63e9293c 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java @@ -128,6 +128,7 @@ public void printTimers() { @Override public void printTimerStatistics(PrintWriter out) { + // todo print reachability here StatisticsPrinter.print(out, "features_time_ms", processFeaturesTimer.getTotalTime()); StatisticsPrinter.print(out, "total_analysis_time_ms", analysisTimer.getTotalTime()); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java index 497f13a1d3c0..1cc0dcbacd10 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java @@ -279,7 +279,7 @@ public Boolean getValue(OptionValues values) { * Build output options. */ @Option(help = "Use new build output style", type = OptionType.User)// - public static final HostedOptionKey BuildOutputUseNewStyle = new HostedOptionKey<>(true); + public static final HostedOptionKey BuildOutputUseNewStyle = new HostedOptionKey<>(false); @Option(help = "Prefix build output with ':'", type = OptionType.User)// public static final HostedOptionKey BuildOutputPrefix = new HostedOptionKey<>(false); From aed8948f9958abc60b5e700554eff6bc0939e5ca Mon Sep 17 00:00:00 2001 From: David Kozak Date: Wed, 19 Jan 2022 13:59:41 +0100 Subject: [PATCH 64/65] fixes after rebase --- substratevm/mx.substratevm/suite.py | 2 +- .../graal/pointsto/ReachabilityAnalysis.java | 4 ++-- .../graal/pointsto/meta/AnalysisType.java | 4 ---- .../ReachabilityObjectScanner.java | 22 ++++++++++++++----- .../com/oracle/svm/hosted/FeatureImpl.java | 12 ++-------- .../NativeImageReachabilityAnalysis.java | 4 ++-- .../oracle/svm/hosted/code/CompileQueue.java | 3 --- 7 files changed, 24 insertions(+), 27 deletions(-) diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 183675027140..2f5c63c82c87 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -415,7 +415,7 @@ "dependencies": [ "com.oracle.graal.pointsto", ], - "checkstyle": "com.oracle.graal.pointsto", + "checkstyle": "com.oracle.svm.core", "javaCompliance": "11+", "annotationProcessors": [ "compiler:GRAAL_PROCESSOR", diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ReachabilityAnalysis.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ReachabilityAnalysis.java index 8bec56be5701..268d70096250 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ReachabilityAnalysis.java @@ -83,7 +83,7 @@ default boolean markFieldUnsafeAccessed(AnalysisField field) { if (!field.isUnsafeAccessed()) { /* Register the field as unsafe accessed. */ field.registerAsAccessed(); - field.registerAsUnsafeAccessed(getUniverse()); + field.registerAsUnsafeAccessed(); /* Force the update of registered unsafe loads and stores. */ forceUnsafeUpdate(field); return true; @@ -99,7 +99,7 @@ default void registerAsUnsafeAccessed(AnalysisField field, UnsafePartitionKind p if (!field.isUnsafeAccessed()) { /* Register the field as unsafe accessed. */ field.registerAsAccessed(); - field.registerAsUnsafeAccessed(getUniverse(), partitionKind); + field.registerAsUnsafeAccessed(partitionKind); /* Force the update of registered unsafe loads and stores. */ forceUnsafeUpdate(field); } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java index ef1301e92ada..cbcfe86edaca 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java @@ -444,10 +444,6 @@ public boolean registerAsAllocated(Node node) { /** Register the type as instantiated with all its super types. */ private void registerAsInstantiated(UsageKind usageKind) { - assert isAllocated.get() || isInHeap.get(); - assert isArray() || (isInstanceClass() && !Modifier.isAbstract(getModifiers())) : this; - universe.hostVM.checkForbidden(this, usageKind); - forAllSuperTypes(t -> t.instantiatedSubtypes.add(this)); } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityObjectScanner.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityObjectScanner.java index 85e5dd16d5a2..39a2ec300603 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityObjectScanner.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityObjectScanner.java @@ -33,6 +33,7 @@ import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; +// todo resolve return values public class ReachabilityObjectScanner implements ObjectScanningObserver { private final ReachabilityAnalysis bb; @@ -44,41 +45,52 @@ public ReachabilityObjectScanner(BigBang bb, AnalysisMetaAccess access) { } @Override - public void forRelocatedPointerFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) { + public boolean forRelocatedPointerFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue, ObjectScanner.ScanReason reason) { field.registerAsAccessed(); if (fieldValue.isNonNull() && fieldValue.getJavaKind() == JavaKind.Object) { // todo mark as instantiated // bb.markTypeInstantiated(constantType(bb, fieldValue)); } + return true; } @Override - public void forNullFieldValue(JavaConstant receiver, AnalysisField field) { + public boolean forNullFieldValue(JavaConstant receiver, AnalysisField field, ObjectScanner.ScanReason reason) { if (receiver != null) { bb.markTypeReachable(constantType(receiver)); } bb.markTypeReachable(field.getType()); // System.out.println("Scanning field " + field); + return true; } @Override - public void forNonNullFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) { + public boolean forNonNullFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue, ObjectScanner.ScanReason reason) { if (receiver != null) { bb.markTypeReachable(constantType(receiver)); } bb.markTypeReachable(field.getType()); // System.out.println("Scanning field " + field); + return true; } @Override - public void forNullArrayElement(JavaConstant array, AnalysisType arrayType, int elementIndex) { + public boolean forNullArrayElement(JavaConstant array, AnalysisType arrayType, int elementIndex, ObjectScanner.ScanReason reason) { bb.markTypeReachable(arrayType); + return true; } @Override - public void forNonNullArrayElement(JavaConstant array, AnalysisType arrayType, JavaConstant elementConstant, AnalysisType elementType, int elementIndex) { + public boolean forNonNullArrayElement(JavaConstant array, AnalysisType arrayType, JavaConstant elementConstant, AnalysisType elementType, int elementIndex, ObjectScanner.ScanReason reason) { bb.markTypeReachable(arrayType); bb.markTypeInstantiated(elementType); + return true; + } + + @Override + public void forEmbeddedRoot(JavaConstant root, ObjectScanner.ScanReason reason) { + bb.markTypeReachable(constantType(root)); + bb.markTypeInstantiated(constantType(root)); } @Override diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/FeatureImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/FeatureImpl.java index 6f25b7c8a8c2..0a374dbe949a 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/FeatureImpl.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/FeatureImpl.java @@ -381,15 +381,7 @@ public void registerAsUnsafeAccessed(Field field) { } public boolean registerAsUnsafeAccessed(AnalysisField aField) { - if (!aField.isUnsafeAccessed()) { - /* Register the field as unsafe accessed. */ - aField.registerAsAccessed(); - aField.registerAsUnsafeAccessed(); - /* Force the update of registered unsafe loads and stores. */ - bb.forceUnsafeUpdate(aField); - return true; - } - return false; + return bb.markFieldUnsafeAccessed(aField); // if (!field.isUnsafeAccessed()) { // /* Register the field as unsafe accessed. */ // field.registerAsAccessed(); @@ -398,7 +390,7 @@ public boolean registerAsUnsafeAccessed(AnalysisField aField) { // bb.forceUnsafeUpdate(field); // return true; // } - return bb.markFieldUnsafeAccessed(aField); + } public void registerAsFrozenUnsafeAccessed(Field field) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java index 2a2d9678a6dc..be6adac48e57 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImageReachabilityAnalysis.java @@ -66,7 +66,7 @@ public NativeImageReachabilityAnalysis(OptionValues options, AnalysisUniverse un super(options, universe, providers, universe.hostVM(), executor, heartbeatCallback, new SubstrateUnsupportedFeatures(), methodSummaryProvider); this.annotationSubstitutionProcessor = annotationSubstitutionProcessor; this.strengthenGraalGraphs = SubstrateOptions.parseOnce(); - this.dynamicHubInitializer = new DynamicHubInitializer(universe, metaAccess, unsupportedFeatures, providers.getConstantReflection()); + this.dynamicHubInitializer = new DynamicHubInitializer(metaAccess, unsupportedFeatures, providers.getConstantReflection()); } @Override @@ -112,7 +112,7 @@ public void checkUserLimitations() { private void scanHub(ObjectScanner objectScanner, AnalysisType type) { SVMHost svmHost = (SVMHost) hostVM; JavaConstant hubConstant = SubstrateObjectConstant.forObject(svmHost.dynamicHub(type)); - objectScanner.scanConstant(hubConstant, ObjectScanner.ScanReason.HUB); + objectScanner.scanConstant(hubConstant, ObjectScanner.OtherReason.HUB); } private void handleUnknownValueField(AnalysisField field) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java index 79225beb3ae9..b5e7d66ac62f 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java @@ -172,9 +172,6 @@ import com.oracle.svm.hosted.phases.HostedGraphBuilderPhase; import com.oracle.svm.hosted.phases.ImageBuildStatisticsCounterPhase; import com.oracle.svm.hosted.phases.ImplicitAssertionsPhase; -import com.oracle.svm.hosted.phases.StrengthenStampsPhase; -import com.oracle.svm.hosted.reporting.ProgressReporter; -import com.oracle.svm.hosted.reporting.ProgressReporter.ReporterClosable; import com.oracle.svm.hosted.substitute.DeletedMethod; import com.oracle.svm.util.ImageBuildStatistics; From 07bed081bfe49b5da25ad012bf62f8b4c6880584 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Mon, 24 Jan 2022 11:22:11 +0100 Subject: [PATCH 65/65] wip --- .../src/com/oracle/svm/hosted/meta/HostedType.java | 6 +++++- .../src/com/oracle/svm/hosted/meta/TypeCheckBuilder.java | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedType.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedType.java index 3c079e52d2fd..ec89a1afc9b9 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedType.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedType.java @@ -328,7 +328,11 @@ public ResolvedJavaMethod resolveConcreteMethod(ResolvedJavaMethod m, ResolvedJa * Check that the SharedType implementation, which is used for JIT compilation, gives the * same result as the hosted implementation. */ - assert hResult == null || isWordType() || hResult.equals(SharedType.super.resolveConcreteMethod(method, callerType)); + boolean condition = hResult == null || isWordType() || hResult.equals(SharedType.super.resolveConcreteMethod(method, callerType)); + if (!condition) { + System.err.println("condition failed for " + m); + } + assert condition; return hResult; } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/TypeCheckBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/TypeCheckBuilder.java index bbc213d7e1af..064c4e054a2d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/TypeCheckBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/TypeCheckBuilder.java @@ -417,9 +417,13 @@ public void buildTypeInformation(HostedUniverse hUniverse) { } boolean isInstantiated = type.getWrapped().isInstantiated(); - assert !isInstantiated || + boolean condition = !isInstantiated || ((type.isInstanceClass() && !Modifier.isAbstract(type.getModifiers())) || type.isArray()); + if (!condition) { + System.err.println("condition broken for " + type); + } + assert condition; if (subtypeStampType == null) { /* Type has no instantiated subtypes. */